13

Ho una classe che eredita da un List<MagicBean>. Funziona bene e come previsto in tutti gli aspetti tranne uno: quando aggiungo l'attributo [DebuggerDisplay]. Anche se guardare List ha il suo valore come [DebuggerDisplay("Count = {Count}")], se io copio e incollo il tutto sul mio, perdo la capacità di guardare direttamente tutti i MagicBeans che ho senza eseguire il drill in base-> membri privati ​​durante il debug.Come rendere [DebuggerDisplay] rispettare le classi ereditate o almeno lavorare con le collezioni?

Come ottengo il meglio di entrambi i mondi? IE: valore personalizzato nella colonna valore e Visual Studio non nasconde i miei magic bean da me?

risposta

9

È possibile ottenere l'effetto è necessario utilizzando l'attributo DebuggerTypeProxy. È necessario creare una classe per fare un debug "visualizzazione" della vostra lista ereditata:

internal sealed class MagicBeanListDebugView 
{ 
    private List<MagicBean> list; 

    public MagicBeanListDebugView(List<MagicBean> list) 
    { 
     this.list = list; 
    } 

    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] 
    public MagicBean[] Items{get {return list.ToArray();}} 
} 

Si può quindi dichiarare questa classe per essere utilizzato dal debugger per la visualizzazione la classe, insieme con l'attributo DebuggerDisplay:

[DebuggerDisplay("Count = {Count}")] 
[DebuggerTypeProxy(typeof(MagicBeanListDebugView))] 
public class MagicBeanList : List<MagicBean> 
{} 

Questo ti darà il messaggio "Numero = 3" quando passi con il mouse su un'istanza dell'elenco ereditato in Visual Studio e una vista degli elementi nell'elenco quando espandi il nodo radice, senza dover eseguire il drill giù nelle proprietà di base.

Utilizzare ToString() per ottenere l'output di debug in modo specifico non è un buon approccio, a meno che, naturalmente, non si stia già eseguendo l'override di ToString() per l'uso nel proprio codice, nel qual caso è possibile utilizzarlo.

+0

Nifty, è utile, ma sembra piuttosto copia e incolla.Non posso testare adesso, ma c'è un modo in cui posso usare il codice che List utilizza già, o per lo meno essere in grado di scrivere una versione generica una volta? Non vorrei scrivere questo per ogni classe di container personalizzata. – MighMoS

+0

Dopo aver scavato un po ', a quanto pare la risposta è no. – MighMoS

2

Dopo aver esaminato l'articolo "Using DebuggerDisplay Attribute" su MSDN, suggeriscono che è possibile sovrascrivere la funzione ToString() della classe come opzione alternativa anziché utilizzare l'attributo DebuggerDisplay. L'override del metodo ToString() non nasconde neanche i tuoi fagioli.

Se un oggetto C# ha un sovrascritto ToString(), il debugger chiamerà l'override e mostrare il suo risultato al posto dello standard {}. Quindi, se hai sostituito ToString(), devi fare in modo che non debba utilizzare DebuggerDisplay. Se si utilizza entrambi, l'attributo DebuggerDisplay ha la precedenza sull'override di ToString() .

Sei in grado di sovrascrivere il metodo ToString() sulla classe o lo stai utilizzando per altri scopi?

Non so se l'hai già preso in considerazione oppure no, ma ho pensato di suggerire che solo l'aiuto lo aiuta. :-)

Per completezza in modo che chiunque altro possa svelarlo rapidamente; ecco un esempio veloce che ho fatto:

namespace StackOverflow 
{ 
    //broken BeanPouch class that uses the DebuggerDisplay attribute 
    [System.Diagnostics.DebuggerDisplay("Count = {Count}")] 
    class BrokenBeanPouch : List<MagicBean> 
    { } 

    //working BeanPouch class that overrides ToString 
    class WorkingBeanPouch : List<MagicBean> 
    { 
     public override string ToString() 
     { 
      return string.Format("Count = {0}", this.Count); 
     } 
    } 

    class Program 
    { 
     static WorkingBeanPouch myWorkingBeans = new WorkingBeanPouch() 
     { 
      new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m } 
     }; 

     static BrokenBeanPouch myBrokenBeans = new BrokenBeanPouch() 
     { 
      new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m } 
     }; 

     static void Main(string[] args) 
     { 
      //break here so we can watch the beans in the watch window 
      System.Diagnostics.Debugger.Break(); 
     } 
    } 

    class MagicBean 
    { 
     public decimal Value { get; set; } 
    }  
} 
0

Usa attribuiscono la DebuggerDisplay in questo modo:

[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]` 
class Project 
{ 
    int ID{get;set;} 
    IList<Customer> Customers{get;set;} 
} 

qualche info in più here.