它总是合适的,但要仔细考虑你所展示的内容背后的意图
一个更好的问题是问:
为什么要覆盖 ToString()?
ToString() 是进入对象状态的窗口。强调状态为要求。强烈的 OOP 语言(如 Java/C#)通过将所有内容封装在一个类中来滥用 OOP 模型。想象一下,您正在使用一种不遵循强大的 OOP 模型的语言进行编码;考虑您是使用类还是函数。如果您将其用作函数(即动词、动作)并且内部状态仅在输入/输出之间临时维护,则 ToString() 不会增加价值。
就像其他人提到的那样,考虑使用 ToString() 输出的内容很重要,因为调试器或其他系统可以使用它。
我喜欢把 ToString 方法想象成一个对象的 --help 参数。它应该简短、易读、明显且易于显示。它应该显示对象是什么而不是它的作用。考虑到所有这些,让我们考虑...
用例 - 解析 TCP 数据包:
不是仅应用程序级别的网络捕获,而是具有更多内容的东西,例如 pcap 捕获。
您只想为 TCP 层重载 ToString(),以便将数据打印到控制台。它会包括什么?您可能会发疯并解析所有 TCP 详细信息(即 TCP 很复杂)...
其中包括:
- 源端口
- 目的端口
- 序列号
- 确认号码
- 数据偏移
- 标志
- 窗口偏移
- 校验和
- 紧急指针
- 选项(我什至不会去那里)
但是,如果您在 100 个数据包上调用 TCP.ToString(),您会想要接收所有这些垃圾吗?当然不是,这将是信息过载。简单明了的选择也是最明智的...
公开人们期望看到的内容:
我更喜欢一个易于人类解析的合理输出,但YMMV。
TCP:[destination:000, source:000]
没什么复杂的,输出不是供机器解析的(即除非人们滥用您的代码),其预期目的是为了人类可读性。
但是我之前谈到的所有其他有趣的信息呢,不是也很有用吗?我会解决的,但首先...
ToString() 是有史以来最有价值和未被充分利用的方法之一
有两个原因:
- 人们不明白 ToString() 的用途
- 基类“对象”缺少另一个同样重要的字符串方法。
原因 1 - 不要滥用 ToString() 的用处:
很多人使用 ToString() 来提取对象的简单字符串表示。C# 手册甚至指出:
ToString 是 .NET Framework 中的主要格式化方法。它将对象转换为其字符串表示形式,以便它适合显示。
展示,不做进一步处理。这并不意味着,使用我上面对 TCP 数据包的漂亮字符串表示,并使用正则表达式 ::cringe:: 拉取源端口。
正确的做法是直接在 SourcePort 属性上调用 ToString() (顺便说一句,它是一个 ushort 所以 ToString() 应该已经可用)。
如果您需要更健壮的东西来打包复杂对象的状态以进行机器解析,那么最好使用结构化序列化策略。
幸运的是,这样的策略很常见:
- 可序列化 (C#)
- 泡菜(蟒蛇)
- JSON(Javascript 或任何实现它的语言)
- 肥皂
- ETC...
注意:除非您使用 PHP,因为 herp-derp 有一个函数用于该 ::snicker::
原因 2 - ToString() 还不够:
我还没有看到一种在核心实现这一点的语言,但我已经在野外看到并使用了这种方法的变体。
其中一些包括:
- ToVerboseString()
- ToString(详细=真)
基本上,应该描述 TCP 数据包状态的毛茸茸的混乱,以提高人类可读性。为了避免在谈论 TCP 时“打死马”,我将“指责”我认为 ToString() 和 ToVerboseString() 未得到充分利用的 #1 案例……
用例 - 数组:
如果您主要使用一种语言,那么您可能对该语言的方法感到满意。对于像我这样在不同语言之间跳跃的人来说,不同的方法的数量可能会令人恼火。
也就是说,这让我感到恼火的次数超过了每个印度教神所有手指的总和。
在各种情况下,语言使用常见的hack和一些正确的方法。有些需要重新发明轮子,有些需要浅转储,有些需要深转储,它们都没有按照我希望的方式工作......
我要的是一个非常简单的方法:
print(array.ToString());
输出:'Array[x]' 或 'Array[x][y]'
其中 x 是第一个维度中的项目数,y 是第二个维度中的项目数,或者表示第二个维度是锯齿状的某个值(可能是最小/最大范围?)。
和:
print(array.ToVerboseString());
以漂亮的印刷品输出整个she-bang,因为我欣赏漂亮的东西。
希望这能对困扰我很久的话题有所启发。至少我为 PHPers 撒了一点巨魔诱饵来否决这个答案。