在C#中,为什么String是一个类似于值类型的引用类型?
一个String是一个引用类型,即使它具有值类型的大多数特征,例如不可变,并且已经重载==来比较文本,而不是确保它们引用同一个对象。
为什么不是字符串只是一个值类型呢?
字符串不是值类型,因为它们可能很大,并且需要存储在堆中。 值类型是(在CLR的所有实现中)存储在堆栈上的。 堆栈分配字符串会破坏各种各样的东西:堆栈只有1MB,你必须打包每个字符串,招致副本处罚,你不能实习字符串,并且内存使用会膨胀等等。
(编辑:增加了关于值类型存储是一个实现细节的澄清,导致这种情况下,我们有一个值类型不是从System.ValueType继承的类型。谢谢Ben。)
它不是一种值类型,因为如果它是一个值类型,那么性能(空间和时间!)会很糟糕,并且它的值必须在每次传递给方法时返回,并且必须被复制,等等。
它有价值的语义来保持世界的理智。 你能想象如果编码是多么困难
string s = "hello";
string t = "hello";
bool b = (s == t);
设b
为false
? 想象一下编码几乎适用于任何应用程序是多么困难。
引用类型和值类型之间的区别基本上是语言设计中的性能折衷。 引用类型在构建和销毁以及垃圾收集时会有一些开销,因为它们是在堆上创建的。 另一方面,数值类型在方法调用(如果数据大小大于指针)上有开销,因为整个对象被复制而不仅仅是指针。 因为字符串可以(通常是)比指针的大小大得多,所以它们被设计为引用类型。 另外,正如Servy指出的,值类型的大小在编译时必须知道,字符串并不总是这样。
可变性问题是一个单独的问题。 引用类型和值类型都可以是可变的或不可变的。 值类型通常是不可变的,因为可变值类型的语义可能会造成混淆。
引用类型通常是可变的,但如果有意义的话可以设计为不可变的。 字符串被定义为不可变的,因为它使某些优化成为可能。 例如,如果相同的字符串文字在同一个程序中出现多次(这很常见),编译器可以重复使用同一个对象。
那么为什么重载“==”来通过文本比较字符串呢? 因为它是最有用的语义。 如果两个字符串由文本相等,由于优化,它们可能会或可能不会是相同的对象引用。 所以比较引用是相当无用的,而比较文本几乎总是你想要的。
更一般地讲,字符串具有所谓的价值语义 。 这是一个比值类型更概括的概念,它是C#特定的实现细节。 值类型具有值语义,但引用类型也可能具有值语义。 当一个类型具有值语义时,您无法确定底层实现是否为引用类型或值类型,因此您可以考虑实现细节。
链接地址: http://www.djcxy.com/p/79183.html上一篇: In C#, why is String a reference type that behaves like a value type?
下一篇: How to display a dynamically allocated array in the Visual Studio debugger?