为什么字符串被密封

问题描述:

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

I am curious why System.String is sealed?

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

I know, I can do whatever I need to do not inheriting it, but still -- why?

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

There are a lot of classes that, by nature, are strings having specific methods and properties. Those are identifiers, emails, names etc.

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

Object oriented design suggests to encapsulate functionality in a specific class. And here we have weird situation that the most usable fundamental type in the most popular object framework is not extendable.

谢谢.

已编辑.

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

Comment regarding immutability. It is easy to hide all state-related things in private methods and allow child classes to have read-only access to class's data.

// 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() {}
}

实际上,实际应用程序中的大多数对象都是字符串.所有这些序列号,ASIN,IMEI等以及名称,注释,按其性质都是字符串.我们从数据库中将它们作为字符串获取,或者将它们作为字符串在网页上的文本框中某处键入,或者由条形码扫描仪等进行罐装.

In fact most of objects in real-world applications are strings. All those serials, ASINs, IMEI etc, as well as names, comments, are string by their nature. We get them as strings from databases, or they typed as string somewhere in text boxes on a web page or canned by barcode scanners etc.

拥有具有特定功能的字符串而不是发明多个类(或多或少都这样做),确实会更好,更安全且更优雅.

And it would be really nice, more secure and much more elegant to have strings with specific features instead of inventing multiple classes, more or less doing the same.

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

There are a lot of classes that, by nature, are strings having specific methods and properties. Those are identifiers, emails, names etc.

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

This specific use-case would be better-handled by composition rather than inheritance, that is: "an email address has a string-representation" instead of "an email address is a string" (because an email address is really a composite of multiple sub-fields that just happen to have a succinct string representation when you're using SMTP).

另一点是,字符串被认为是一种基本类型-从 int 派生没有意义-为什么是字符串?如果要扩展 System.String 的实现,则仅需要从 String 派生-例如,您要覆盖其 GetHashcode 实现-但是可以想像的要覆盖的操作数量非常有限,那么框架维护者为什么要烦恼支持该方案呢?

Another point is that String is meant to be a fundamental type - it doesn't make sense to derive from an int - why a string? You would only need to derive from String if you want to extend System.String's implementation - for example, you want to override its GetHashcode implementation - but the number of operations you could conceivably want to override is very limited, so why should the framework maintainers bother with supporting that scenario?

正如@Steve在评论中所链接的那样,Eric Lippert的这篇博客文章还解释了为什么被密封的许多类,尤其是从维护PoV:

As @Steve linked in the comments, this blog post by Eric Lippert also explains why many classes are sealed, especially from a maintenance PoV: https://blogs.msdn.microsoft.com/ericlippert/2004/01/22/why-are-so-many-of-the-framework-classes-sealed/

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

Finally, if you really want your own string behaviour (which is quite possible: you can length-prefixed strings, null-terminated strings, strings that exist as defined ranges in a larger string buffer, a linked-list based string, a Trie that holds multiple strings in a memory-efficient manner, a hybrid of multiple approaches, and so on) you can build your own implementation from scratch - none of these need to derive from System.String to exist. Sure, you wouldn't be able to pass it into a class that expects a String value, but that's only fair because perhaps those consumers depend on particular implementation behaviour of System.String (such as runtime performance, immutability, etc).