13

Tengo una clase que hereda de List<MagicBean>. Funciona bien y como se esperaba en todos los aspectos excepto en uno: cuando agrego el atributo [DebuggerDisplay]. A pesar de que mirar List tiene su valor [DebuggerDisplay("Count = {Count}")], si copio y pegé eso en el mío, pierdo la capacidad de mirar directamente a todos los MagicBeans que tengo sin tener que profundizar en los miembros base-> privados mientras se depura.¿Cómo hacer que [DebuggerDisplay] respete las clases heredadas o al menos trabaje con colecciones?

¿Cómo puedo obtener lo mejor de ambos mundos? IE: valor personalizado en la columna de valor, y Visual Studio no oculta mis beans mágicos de mí?

Respuesta

9

Usted puede obtener el efecto que necesita mediante el atributo DebuggerTypeProxy. Es necesario crear una clase para hacer una depuración "visualización" de su lista heredada:

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();}} 
} 

Luego, puede declarar esta clase para ser utilizado por el depurador para mostrar su clase, junto con el atributo DebuggerDisplay:

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

Esto le dará el mensaje "Count = 3" cuando pase el mouse sobre una instancia de su lista heredada en Visual Studio y una vista de los elementos en la lista cuando expanda el nodo raíz, sin tener que hacia abajo en las propiedades de base.

El uso de ToString() para obtener específicamente la salida de depuración no es un buen enfoque, a menos que por supuesto ya esté anulando ToString() para utilizar en otro código, en cuyo caso puede usarlo.

+0

Nifty, es útil, pero parece bastante copiar y pegar.No puedo realizar pruebas en este momento, pero ¿hay alguna forma de que pueda usar el código que Lista ya usa, o al menos poder escribir una versión genérica una vez? Odiaría escribir esto para cada clase de contenedor personalizado. – MighMoS

+0

Después de haber estado cavando, aparentemente la respuesta es no. – MighMoS

2

Después de mirar el artículo "Using DebuggerDisplay Attribute" en MSDN, sugieren que podría anular la función ToString() de su clase como una opción alternativa en lugar de usar el atributo DebuggerDisplay. Anular el método ToString() tampoco ocultará sus beans.

Si un objeto C# tiene una ToString() sustituido, el depurador se llame a la anulación y mostrar su resultado en lugar de la norma {}. Por lo tanto, si ha reemplazado ToString(), usted no tiene que usar DebuggerDisplay . Si usa , el atributo DebuggerDisplay tiene prioridad sobre la anulación de ToString ( ).

¿Puede anular el método ToString() en su clase o lo está utilizando para otros fines?

No sé si ya has considerado esto o no, pero pensé que lo recomendaría por si acaso. :-)

Por completitud para que cualquier otra persona pueda simularlo rápidamente; Aquí está un ejemplo rápido que hice:

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

Uso del DebuggerDisplay atribuyen este modo:

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

Algunos más información here.

Cuestiones relacionadas