C#:应该如何实现ToString()?

时间:2009-09-10 09:09:52

标签: c# tostring

问题是:

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

由于用法不同,有许多不同的实现方式。所以它们太不可靠而不能真正有用。

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


.NET Framework documentation说:

  

此方法返回人类可读的   文化敏感的字符串。

有一个similar question,但不一样。

5 个答案:

答案 0 :(得分:5)

似乎你对一个小小的方法有很大的期望:)据我所知,在很多不同的上下文中使用一般方法并不是一个好主意,特别是当它的行为因类而异时。

以下是我的建议:

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

答案 1 :(得分:2)

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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

因此,我认为默认的ToString方法(没有参数)是Visual Studio调试钩子 - 暗示它通常不应该被重载以供程序在调试上下文之外使用。

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

我理解这是一个相当严格的观点 - 将ToString写成调试器钩子 - 但我发现实现IFormattable似乎是更可靠和可扩展的路径。

答案 4 :(得分:0)

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

在任何情况下,以下是一些有意义的案例(不是详尽的清单):

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

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

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

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