C#调试:[DebuggerDisplay]还是ToString()?

104

提高调试信息的有效性有两种方法,而不是在调试器中看到 {MyNamespace.MyProject.MyClass},它们分别是使用DebuggerDisplayAttributeToString()方法。

using System.Diagnostics;
...

[DebuggerDisplay("Name = {Name}")]
public class Person
{
    public string Name;
}
或者
public class Person
{
    public string Name;
    public override string ToString()
    {
        return string.Format("Name = {0}", Name);
    }
}

有没有任何理由更喜欢其中一个?有没有不推荐同时使用两者的原因?这完全是个人偏好吗?

7个回答

108

使用 [DebuggerDisplay] 只是为了调试器。重写 ToString() 会在运行时对显示产生“副作用”。

这可能是好事,也可能不是。

通常,在调试过程中,您需要更多的信息而不仅仅是标准的ToString()输出,此时您会同时使用两者。

例如,在您的情况下,我认为 "ToString" 的实现很奇怪。我希望 "Person" 类的 ToString() 实现直接返回姓名,而不是 "Name = PersonsName"。然而,在调试过程中,我可能需要额外的信息。


11
补充Reed提到的“副作用”观点:ToString经常被用作“默认显示字符串”,例如,被 Console.WriteLine 或 WPF数据绑定使用。 - Stephen Cleary
当然,字符串的格式只是为了提供一个视觉示例来强调它与DebuggerDisplay给出的字符串的相似性。正如你所说,DebuggerDisplay格式也可以直接返回名称。我理解你关于副作用的观点——这是我正在寻找的区别。我通常不会经常使用类的ToString方法(除了我上面提到的目的),因此它的其他用法对我来说并不明显。谢谢! - bwerks

10
调试器的缓慢也需要考虑到:
调试器在每个调试步骤/断点之后解释DebuggerDisplayAttribute格式表达式。 ToString在您的代码中编译,因此调试器执行速度更快。
对于条件断点也是如此:如果条件表达式在每次执行到断点时由调试器解释太慢,则删除断点并添加临时代码可能很有用,例如:if (condition) Debugger.Break();

8

"当您创建自定义类或结构时,应重写ToString方法,以向客户端代码提供有关您的类型的信息。" — MSDN

如果您不喜欢ToString()返回并在调试器中看到的内容,则可以使用DebuggerDisplayAttribute


2

个人偏好(当所需输出不是真正的100%已知时)

  1. 实现HelperFunction
  2. 通过HelperFunction实现ToString
  3. 通过HelperFunction实现DebuggerDisplay。

现在,未来的编辑可以根据需要区分或保持一致,并且有更好的可追溯性。


1
如果您使用Xamarin开发Android应用程序,那么在观察窗口中将不会显示ToString方法,但是DebuggerDisplay会被显示。

1

DebuggerDisplay 对于一些简单的东西来说,打起来更快。

ToString() 可能会更加复杂,因为你想要查看的数据取决于对象的属性。与 #if DEBUG 语句结合使用,你将拥有一个很好的仅用于调试的数据查看器。没有人会像 "客户端视图" 那样使用 ToString(),因为它太模糊了,任何更改都是不可能在逻辑上维护的。除非提供该字符串是类的唯一目的,并且在调试中也是如此,否则每个人都会显式地调用属性或方法而不是 ToString()

还有 DebuggerBrowsableAttributeDebuggerTypeProxyAttribute,但如果没有真正需要这样的东西,那么这些只是额外的复杂性。


0

DebuggerDisplay 的功能相对有限。你只能使用格式字符串来显示特定成员的值。

如果你想要有条件地显示数据、显示多层深度的数据或聚合数据,ToString() 可能是你唯一的选择。


我认为这些功能相当相似,因为您可以将DebuggerDisplay指向一个计算属性。因此,您可以轻松地返回ToString()结果或自己定制的字符串。[DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] public record Something { private readonly string unique; public Something(string unique) { this.unique = unique; } private string DebuggerDisplay => this.ToString(); public override string ToString() { return $"{typeof(T)}:{this.unique}"; } } - Beachwalker

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