为什么字符串被密封

Dmi*_*ezo 6 .net c#

我很好奇为什么System.String是密封的?

我知道,我可以做任何我不需要继承的事情,但仍然 - 为什么?

有很多类本质上是具有特定方法和属性的字符串.这些是标识符,电子邮件,名称等.

面向对象的设计建议将功能封装在特定的类中.在这里,我们有一种奇怪的情况,即最流行的对象框架中最可用的基本类型是不可扩展的.

谢谢.

编辑.

关于不变性的评论.很容易在私有方法中隐藏所有与状态相关的东西,并允许子类具有对类数据的只读访问权限.

// Safe inheritable immutable string (pseudocode).
class String
{
   // Private state
   private byte[] state;
   private void EditState(byte[]) {}
   // Protected read-only access to state
   protected byte getReadOnlyData() {}
   // Available to child classes overridable methods.
   protected virtual getHashCode() {}
   protected virtual xxx() {}
}
Run Code Online (Sandbox Code Playgroud)

事实上,实际应用程序中的大多数对象都是字符串.所有这些连续出版物,ASIN,IMEI等,以及名称,评论,都是其性质的字符串.我们将它们作为数据库中的字符串,或者在网页上的文本框中键入字符串,或者通过条形码扫描仪等进行封装.

拥有特定功能的字符串,而不是发明多个类,或多或少做同样的事情,这将是非常好,更安全,更优雅.

Dai*_*Dai 12

有很多类本质上是具有特定方法和属性的字符串.这些是标识符,电子邮件,名称等.

这个特定的用例可以通过组合而不是继承来更好地处理,即:"电子邮件地址具有字符串表示"而不是"电子邮件地址是字符串"(因为电子邮件地址实际上是多个组合)当你使用SMTP时恰好碰巧有一个简洁的字符串表示的子字段.

另一点是String是一种基本类型 - 从一个int- 为什么是一个字符串派生出来是没有意义的?您只需要从String扩展System.String的实现中派生出来- 例如,您想要覆盖它的GetHashcode实现 - 但是您可以想象覆盖的操作数量非常有限,那么为什么框架维护者需要支持那个场景?

正如@Steve在评论中所链接的那样,Eric Lippert撰写的这篇博文也解释了为什么许多课程sealed,特别是来自维护PoV:https://blogs.msdn.microsoft.com/ericlippert/2004/01/22/why-are -SO-许多的最框架类密封/

最后,如果你真的想要自己的字符串行为(这很可能:你可以使用长度为前缀的字符串,以空字符结尾的字符串,在更大的字符串缓冲区中存在为定义范围的字符串,基于链表的字符串,Trie以高效内存的方式保存多个字符串,多种方法的混合,等等)您可以从头开始构建自己的实现 - 这些都不需要派生System.String存在.当然,您无法将其传递到需要String值的类中,但这只是公平的,因为这些消费者可能依赖于特定的实现行为System.String(例如运行时性能,不变性等).


nik*_*ita 5

字符串被密封主要是因为它是不可变的并且CLR广泛使用该特征(实习,跨域编组).如果字符串不会被密封,那么所有CLR对字符串不变性的期望都不会花费一分钱.

  • @DmitryKarpezo我认为那是因为1.当所有基本成员都是私有的时候,继承是没有意义的.2.由于我们讨论的是继承,因此当类共享共同行为时应该应用它.现在,当基类是不可变的而另一个不是基本类时,它们本质上并不常见. (2认同)