总的来说,重载ToString()方法是适当的,但需要仔细考虑显示内容的目的。
更好的问题应该是:
为什么要重写ToString()方法?
ToString()方法是查看对象状态的窗口。强调状态是必须的。像Java/C#这样的面向对象的语言通过把所有内容封装在类中来滥用面向对象编程模型。想象一下,如果你使用的是不遵循强OOP模型的语言,你会使用类还是函数。如果你会将其作为函数(即动词、行动)使用,并且内部状态仅在输入/输出之间暂时维护,那么ToString()方法就不会增加价值。
正如其他人提到的,重载ToString()方法时需要考虑显示什么,因为它可能被调试器或其他系统使用。
我喜欢把ToString()方法想象成对象的--help参数。它应该是简短的、可读的、明显的和易于显示的。它应该显示对象是什么而不是做了什么。有了这些考虑,让我们考虑...
用例 - 解析TCP数据包:
不是应用程序级别的网络捕获,而是像pcap捕获这样更具体的东西。
你想为TCP层重载ToString()方法,以便可以将数据打印到控制台。它会包括什么?你可以疯狂地解析所有TCP细节(即TCP很复杂)...
这其中包括:
- 源端口
- 目标端口
- 序列号
- 确认号码
- 数据偏移量
- 标志
- 窗口偏移量
- 校验和
- 紧急指针
- 选项(我甚至不会去那里)
但如果你在100个数据包上调用TCP.ToString()时,你想接收所有这些垃圾信息吗?当然不,这会造成信息过载。最简单和明显的选择也是最明智的选择...
展示人们期望看到的内容:
我更喜欢一个对人类来说易于解析的合理输出,但您的体验可能会有所不同。
TCP:[destination:000, source:000]
没有什么复杂的,输出不是让机器解析的(除非人们正在滥用你的代码),旨在使人更容易阅读。
但是我之前提到的所有其他有用信息怎么样?我会讲到那个问题的,但首先...
ToString()是有史以来最有价值且未被充分利用的方法之一
原因有两个:
- 人们不理解 ToString() 的用途
- 基类 'Object' 缺少另一个同等重要的字符串方法。
原因1-不要滥用 ToString() 的实用性:
很多人使用 ToString() 来提取对象的简单字符串表示形式。C# 手册甚至声明:
ToString 是 .NET Framework 中的主要格式设置方法。它将对象转换为其字符串表示形式,以便于显示。
显示,而不是进一步处理。这并不意味着,拿走我上面 TCP 包的漂亮字符串表示形式,并使用正则表达式提取源端口:: cringe ::。
正确的做法是直接在 SourcePort 属性上调用 ToString()(顺便说一下,它是 ushort,因此 ToString() 应该已经可用)。
如果您需要更强大的东西来打包复杂对象的状态以供机器解析,那么最好使用结构化序列化策略。
幸运的是,这样的策略非常普遍:
- ISerializable (C#)
- Pickle (Python)
- JSON (Javascript 或任何实现它的语言)
- SOAP
- 等...
注意:除非使用 PHP,因为有一个功能可以做到这一点:: snicker ::
原因 2 - ToString() 是不够的:
我还没有看到一种实施该方法的语言,但我已经在野外看到并使用了此方法的变体。
其中一些包括:
- ToVerboseString()
- ToString(verbose=true)
基本上,TCP 数据包的那个毛茸茸的状况应该为人类可读性所描述。为了避免“反复敲打”谈论 TCP,我将“指出”一个我认为 ToString() 和 ToVerboseString() 被低估的 #1 案例...
用例-数组:
如果您主要使用一种语言,则可能对该语言的方法感到满意。对于像我这样在不同语言之间跳跃的人来说,各种各样的方法数量可能会很烦人。
即,这已经困扰我的次数大于每个印度教神的所有手指的总和。
有各种情况,语言使用通用技巧和少数能够正常工作的情况。有些
print(array.ToString());
输出结果: 'Array[x]' 或 'Array[x][y]'
x表示第一维中项目的数量,y表示第二维中项目的数量或者指示第二维是不规则的某个值(如最小/最大范围)。
而且:
print(array.ToVerboseString());
因为我欣赏美丽事物,所以输出整个shebang的漂亮打印版。
希望这能对一个长期困扰我的话题有所启示。至少我在回答中撒了一些PHP大神们下票的“诱饵”。
Console.WriteLine(obj.GetToStringItemsHeadings); Console.WriteLine(obj);
或类似的方式将对象转储出来。 - Rup