2010-02-26 18 views
10

Encuentro útil anular ToString() en muchas de las clases DTO/POCO simples que escribo para mostrar buena información al pasar el ratón sobre instancias dentro del depurador.¿Hay alguna manera de anular automáticamente ToString() en una clase?

Aquí está un ejemplo:

public class IdValue<T> 
    { 
    public IdValue(int id, T value) 
    { 
     Id = id; 
     Value = value; 
    } 

    public int Id { get; private set; } 
    public T Value { get; private set; } 

    public override string ToString() 
    { 
     return string.Format("Id: {0} Value: {1}", Id, Value); 
    } 
    } 

¿Hay una manera de tener .NET automáticamente una anulación de ToString() que enumera a cabo las propiedades públicas o hay una buena convención de seguir?

Respuesta

16

Puede anular ToString en una clase base y luego usar la reflexión en la instancia para descubrir las propiedades públicas de la clase derivada. Pero esto probablemente presentará problemas de rendimiento en otras áreas de tu código. Además, debido a que ToString es utilizado por muchas cosas (String.Format, enlace de datos predeterminado, etc.), la anulación de ToString con fines de depuración hará que sus clases sean menos útiles en otros escenarios.

En su lugar, es posible que desee utilizar el atributo DebuggerDisplay para controlar cómo el depurador muestra información emergente y la información en la ventana del reloj y tal. Estoy bastante seguro de que esto funciona si lo aplicas a una clase base. También puede crear visualizadores personalizados, pero eso es más complicado. Consulte este enlace para obtener más información sobre cómo mejorar la experiencia de visualización del depurador.

Enhancing Debugging

+1

¡Gracias! Todo lo que tenía que hacer era agregar este atributo a la clase que originalmente publiqué y se comportó de la manera que quería: [DebuggerDisplay ("Id: {Id} Valor: {Valor}")] –

0

Esta no es una buena consideración de diseño. Te aconsejo que extraigas valores donde necesites iniciar sesión o que tengas un método de ayuda (puedes usar métodos de extensión en System.Object).

0

aquí una manera que podría hacerse de una manera amigable depurador

public override string ToString() 
{ 
    stringBuilder sb = ... your usual string output 
    AppendDebug(sb); 
    return sb.Tostring(); 
} 


[Conditional("DEBUG")] 
private void AppendDebug(stringBuilder sb) 
{ 
    sb.Append(... debug - specific info) 

} 

El [condicional] atributo es la clave para su pregunta.

+2

ConditionalAttribute es más adecuado para cuando está exponiendo un método a otra persona que llama cuya configuración de compilación no conoce de antemano. En este caso, podría obtener el mismo resultado sin la ambigüedad del sitio de llamada con #if DEBUG. ¡Pero es un atributo muy útil y poco conocido! – Josh

0

Escuche a las personas que le advierten acerca de las consideraciones de rendimiento y/o diseño. Está estrechamente vinculante un comportamiento para satisfacer una necesidad bastante limitada, cuando puede desacoplar sus necesidades mediante el uso de una extensión o decorador.

0

Si no te importa una dependencia externa, se podría recurrir a un marco ayudar con la impresión de todas las propiedades de los objetos como StatePrinter

Un ejemplo de uso

class AClassWithToString 
{ 
    string B = "hello"; 
    int[] C = {5,4,3,2,1}; 

    // Nice stuff ahead! 
    static readonly StatePrinter printer = new StatePrinter(); 
    public override string ToString() 
    { 
    return printer.PrintObject(this); 
    } 
} 
1

Usted podría utilizar JSON:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Web.Script.Serialization; 

namespace ConsoleApplication1 
{ 
    public class IdValue<T> 
    { 
     public IdValue(int id, T value) 
     { 
      Id = id; 
      Value = value; 
     } 

     public int Id { get; private set; } 
     public T Value { get; private set; } 

     public override string ToString() 
     { 
      return new JavaScriptSerializer().Serialize(this); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var idValue = new IdValue<string>(1, "Test"); 
      Console.WriteLine(idValue); 
      Console.ReadKey(); 
     } 
    } 
} 

que da a esta salida:

{"Id": 1, "Valor": "Prueba"}

Cuestiones relacionadas