有没有一种方法可以自动覆盖一个类的ToString()方法?

11

我发现对于我编写的许多简单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个回答

16

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

相反,你可以使用DebuggerDisplay特性来控制调试器在悬停提示和监视窗口中显示的信息。我相信如果将其应用于基类,它也可以起作用。你还可以创建自定义的可视化对象,但这需要更多的操作。请查看此链接以获取有关增强调试器显示体验的更多信息。

增强调试


1
谢谢!我所要做的就是将这个属性添加到我最初发布的类中,它就会按照我想要的方式运行:[DebuggerDisplay("Id: {Id} Value: {Value}")] - Rob Packwood

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

这是HTML代码,内容与编程有关:

输出如下:

{"Id":1,"Value":"Test"}


1
如果您不介意使用外部依赖,您可以使用一个框架来帮助打印所有对象属性,例如 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);
  }
}

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 )

}

[Conditional] 属性是您问题的关键。


3
ConditionalAttribute 通常用于暴露给其他调用者的方法,而你事先不知道他们的构建配置。在这种情况下,你可以使用 #if DEBUG 来达到同样的效果而不会产生调用地点的歧义。但是,这是一个非常有用但鲜为人知的属性! - Josh

0

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


0
听那些警告你关于性能和/或设计考虑的人。当你可以使用扩展或装饰器来解耦你的需求时,你正在紧密地绑定一种行为以适应一个相当有限的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接