7

问题是:

  • GUI 库喜欢ToString用作类的默认表示。那里需要本地化。
  • ToString用于记录。它应该在那里提供与编程相关的信息,不被翻译并且包括内部状态,如代理键和枚举值。
  • ToString被许多将对象作为参数的字符串操作使用,例如String.Format,在写入流时。根据你期望的不同的上下文。
  • ToString如果同一对象有许多不同的表示,例如,则太有限了。有长有短的形式。

由于用途不同,实现方式也有很多种。所以它们太不可靠而不能真正有用。

应该如何ToString实施才能有用?什么时候应该ToString使用,什么时候应该避免?


.NET Framework 文档说:

此方法返回对区域性敏感的人类可读字符串。

有一个类似的问题,但不一样。

4

5 回答 5

5

看起来你对一个小小的方法寄予厚望:) 据我所知,在这么多不同的上下文中使用通用方法并不是一个好主意,特别是当它的行为因类而异时。

以下是我的建议:

1.不要让 GUI 库使用对象的 ToString()。而是使用更有意义的属性(几乎所有控件都可以自定义以显示除 ToString 之外的其他属性),例如使用 DisplayMember。2.当获取有关对象的一些信息(用于日志记录或其他用途)时,让某人决定(另一个对象或对象本身)应该提供什么以及应该如何显示它。(策略模式可能会派上用场)

于 2009-09-10T09:31:59.380 回答
2

这是一篇很好的文章,它解释了覆盖 System.Object.ToString() 和实现 IFormattable

于 2009-09-10T09:30:15.950 回答
1

这取决于您的班级的预期用途。许多类没有自然的字符串表示(即 Form 对象)。然后我会将 ToString 实现为在调试时有用的信息方法(表单文本、大小等)。如果该类旨在向用户提供信息,那么我会将 ToString 实现为该值的默认表示形式。例如,如果您有一个 Vector 对象,则 ToString 可能会将该向量作为 X 和 Y 坐标返回。如果有其他方法来描述该类,我还会在这里添加替代方法。因此,对于 Vector,我可能会添加一个方法,该方法将描述作为角度和长度返回。

出于调试目的,您可能还希望将 DebuggerDisplay 属性添加到您的类中。这告诉了如何在调试器中显示类,但它不影响字符串表示。

您可能还需要考虑使 ToString 返回的值可解析,以便您可以从字符串表示创建对象。就像您可以使用 Int32.Parse 方法一样。

于 2009-09-10T09:18:42.890 回答
1

另一个需要考虑的问题是 ToString 和 Visual Studio 的调试器之间的紧密集成。Watch 窗口将 ToString 的结果显示为表达式的值,因此如果您的方法执行任何延迟加载、有任何副作用或需要很长时间,那么您可能会看到奇怪的行为或调试器可能会挂起. 诚然,这些品质并不是设计良好的 ToString 方法的标志,但它们确实发生了(例如,一个天真的“从数据库中获取翻译”实现)。

因此,我认为默认 ToString 方法(不带参数)是一个 Visual Studio 调试钩子——这意味着它通常不应被重载以供调试上下文之外的程序使用。

虽然知道的人利用调试属性(DebuggerTypeProxyAttribute、DebuggerDisplayAttribute、DebuggerBrowsableAttribute)来自定义调试器,但许多人(包括我自己)通常认为由 ToString 生成并显示在 Watch 窗口中的默认输出就足够了。

我知道这是一个相当严格的观点——将 ToString 写为调试器钩子——但我发现实现 IFormattable 似乎是更可靠和可扩展的路线。

于 2009-09-15T19:34:19.200 回答
0

就个人而言,我不经常实现 ToString。在许多情况下,它没有多大意义,因为类型的主要作用可能是定义行为,而不是数据。在其他情况下,它根本无关紧要,因为没有客户需要它。

无论如何,以下是一些有意义的情况(不是详尽的列表):

  • 如果可以想象 ToString 的结果可以被解析回该类型的实例而不会丢失数据。
  • 当类型具有简单(即不复杂)值时。
  • 当类型的主要目的是将数据格式化为文本时。

我不同意您列出的使用场景之间存在冲突。当显示是主要目的时, ToString 应该提供用户友好的文本,但是对于日志记录(或者更确切地说,如您所描述的那样,用于跟踪)我会说您在任何情况下都不应该跟踪特定于 UI 的元素,而是一个对象,其目的是写入详细的跟踪数据。

所以没有冲突,因为根据单一责任原则,它不应该是同一类型。

请记住,如果您需要更多控制权,您始终可以重载 ToString 方法。

于 2009-09-10T09:27:12.120 回答