String是一种引用类型,尽管它具有值类型的大多数特征,例如不可变和重载==以比较文本,而不是确保它们引用同一个对象。

为什么字符串不只是一个值类型呢?


当前回答

不仅字符串是不可变的引用类型。 还有多类型转换委托。 这就是为什么写信是安全的

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

我认为字符串是不可变的,因为这是使用它们和分配内存的最安全的方法。 为什么它们不是值类型?以前的作者对堆栈大小等的看法是正确的。我还会添加,使字符串引用类型允许在程序中使用相同的常量字符串时节省程序集大小。如果你定义

string s1 = "my string";
//some code here
string s2 = "my string";

“my string”常量的两个实例很可能只在程序集中分配一次。

如果你想像一般引用类型一样管理字符串,把字符串放在一个新的StringBuilder(string s)中。或者使用MemoryStreams。

如果您要创建一个库,并希望在函数中传递一个巨大的字符串,则可以将参数定义为StringBuilder或Stream。

其他回答

并不像字符串由字符数组组成那么简单。我把字符串看作字符数组[]。因此,它们位于堆上,因为引用内存位置存储在堆栈上,并且指向数组在堆上内存位置的开始。字符串大小在分配之前是不知道的…非常适合堆。

这就是为什么字符串是不可变的,因为当你改变它时,即使它的大小相同,编译器也不知道,它必须分配一个新的数组,并将字符分配到数组中的位置。如果你认为字符串是语言保护你不需要动态分配内存的一种方式,这是有道理的(像编程一样阅读C语言)

字符串不是值类型,因为它们可能很大,需要存储在堆上。值类型(在CLR的所有实现中)存储在堆栈上。堆栈分配字符串会破坏各种各样的事情:32位的堆栈只有1MB, 64位的堆栈只有4MB,你必须装箱每个字符串,导致复制惩罚,你不能实习字符串,内存使用会膨胀,等等……

(编辑:增加了关于值类型存储是实现细节的说明,这导致了这种情况,即我们有一个具有值语义的类型没有从System.ValueType继承。由于本。)

它不是一个值类型,因为如果它是一个值类型,并且它的值每次传递给方法或从方法返回时都必须复制,那么性能(空间和时间!)会很糟糕。

它有价值语义来保持世界的理智。你能想象编码有多困难吗

string s = "hello";
string t = "hello";
bool b = (s == t);

设b为假?想象一下编写任何应用程序是多么困难。

简单地说,任何具有一定大小的值都可以被视为值类型。

不仅字符串是不可变的引用类型。 还有多类型转换委托。 这就是为什么写信是安全的

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

我认为字符串是不可变的,因为这是使用它们和分配内存的最安全的方法。 为什么它们不是值类型?以前的作者对堆栈大小等的看法是正确的。我还会添加,使字符串引用类型允许在程序中使用相同的常量字符串时节省程序集大小。如果你定义

string s1 = "my string";
//some code here
string s2 = "my string";

“my string”常量的两个实例很可能只在程序集中分配一次。

如果你想像一般引用类型一样管理字符串,把字符串放在一个新的StringBuilder(string s)中。或者使用MemoryStreams。

如果您要创建一个库,并希望在函数中传递一个巨大的字符串,则可以将参数定义为StringBuilder或Stream。