有没有办法在类上自动覆盖ToString()?

时间:2010-02-26 17:34:33

标签: c# .net

我发现在我编写的许多简单的DTO / POCO类上覆盖ToString()很有用,当将鼠标悬停在调试器中的实例上时显示一些好的信息。

以下是一个例子:

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

在.NET中是否有一种方法可以自动使用ToString()覆盖来列出公共属性,还是有一个很好的约定?

6 个答案:

答案 0 :(得分:16)

您可以在基类中重写ToString,然后在实例上使用反射来发现派生类的公共属性。但这可能会在代码的其他方面引入性能问题。另外,因为ToString被很多东西使用(String.Format,默认数据绑定等)来覆盖ToString用于调试目的会使你的类在其他场景中不那么有用。

相反,您可能希望使用DebuggerDisplay属性来控制调试器在监视窗口中显示悬停提示和信息的方式等。如果你将它应用于基类,我很确定这是有效的。您还可以创建自定义可视化工具,但更复杂。有关增强调试器显示体验的更多信息,请查看此链接。

Enhancing Debugging

答案 1 :(得分:1)

您可以使用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();
        }
    }
}

这给出了这个输出:

{ “ID”:1, “值”: “测试”}

答案 2 :(得分:0)

这不是一个好的设计考虑因素。我建议你提取你需要记录它们的值或者有一个帮助方法(你可以在System.Object上使用扩展方法)。

答案 3 :(得分:0)

这是一种可以以调试器友好的方式完成的方式

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 )

}

[有条件]属性是您问题的关键。

答案 4 :(得分:0)

聆听那些警告您性能和/或设计注意事项的人。当你可以通过使用扩展或装饰来解除你的需求时,你就会紧紧地绑定一个行为以满足非常有限的需求。

答案 5 :(得分:0)

如果你不介意外部依赖,你可以转向一个框架,帮助打印所有对象属性,如StatePrinter

示例用法

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