一个字符串是即使它具有最的值类型的特征,例如是不可变的,并且具有==重载到文本比较,而不是确保它们引用相同的对象的引用类型。

为什么没有字符串只是一个值然后输入?

有帮助吗?

解决方案

的字符串不是值类型,因为它们可以是巨大的,并且需要被存储在堆上。值类型(在作为尚未的CLR的所有实现)存储在栈上。堆栈分配的字符串将打破各种各样的东西:堆栈是32位和4MB的64位只有1MB,你必须框中的每个字符串,招致罚抄,你不能实习生字符串和内存使用情况将气球等...

(编辑:。添加澄清值类型的存储是一个实现细节,这导致这种情况,我们有与值语义学对不从System.ValueType由于本继承一个类型)

其他提示

这是不是值类型,因为性能(空间和时间!),将是可怕的,如果它是一个值类型和它的价值有充分的它传递给时间被复制,并从方法返回,等等。

它具有值的语义保持世界清醒。你能想象这将是多么困难的代码,如果

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

bfalse?试想编码多么困难几乎任何应用程序会。

引用类型和值的类型之间的区别,基本上在该语言的设计性能权衡。引用类型对建设和破坏,垃圾收集一些开销,因为他们是在堆上创建的。在另一方面值类型对方法调用(如果该数据大小大于指针大)的开销,因为整个对象被复制,而不是仅仅一个指针。因为字符串可以是(并且通常是)比指针的大小大得多,它们被设计成引用类型。另外,作为Servy指出的,值类型的尺寸必须在编译时,这并不总是为字符串的情况下是已知的。

可变性的问题是一个单独的问题。两个参考类型和值类型可以是可变的或不可变的。值类型通常是不可变的,虽然,由于可变的值类型的语义可以是混乱。

引用类型通常是可变的,但是如果它是有道理可以设计为不可变的。因为它使某些优化可能,字符串被定义为不可变的。例如,如果相同的字符串文字出现在同一程序多次(这是相当常见的),编译器可以重复使用相同的对象。

那么,为什么“==”超载通过文字比较字符串?因为它是最有用的语义。如果两个字符串相等通过文本,它们可以是或可以不是相同的对象基准由于优化。所以,比较引用是相当无用的,而比较文字几乎都是你想要的。

说到更一般地,字符串具有所谓的值语义即可。这比值类型,这是一个C#特定实现细节的更一般的概念。值类型有值语义,但引用类型也可能有值语义。当一个类型有值语义,你真的不能告诉如果底层的实现是引用类型或值类型,所以你可以认为是一个实现细节。

这是一个迟到的回答到一个老问题,但其他所有的答案都缺少了这一点,这是.NET没有仿制药,直到.NET 2.0在2005年。

String是一个引用类型,而不是一个值类型,因为的这是至关重要的Microsoft,以确保字符串可以被存储在最有效的方式在非泛型集合下,如System.Collection.ArrayList

存储一个值型在非泛型集合需要一个特殊的转换到object被称为装箱的类型。当CLR盒值类型,它封装了System.Object并且将其存储在托管堆上内的值。

读取从集合中值需要被称为取消装箱的逆操作。

两者装箱和拆箱具有不可忽略的成本:拳击需要额外的配置,开箱需要类型检查

一些权利要求的答案不正确地string不可能已被实现为值类型,因为它的尺寸是可变的。实际上它是容易实现的字符串作为使用小弦优化策略的固定长度的数据结构:串将被存储在存储器直接作为不同的是将被存储作为指针到外部缓冲器大串的Unicode字符序列。这两种表示可以被设计成具有相同的固定长度,即指针的大小。

如果仿制药已经从一个我猜有字符串值类型很可能是一个更好的解决方案,用更简单的语义,更好的内存使用量和更好的缓存局部性一天存在。仅包含小弦List<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";

有机会,“我的字符串”的两个实例常数将在汇编一次分配。

如果你想管理像往常一样引用类型的字符串,把字符串的新的StringBuilder(字符串s)内。或使用MemoryStreams。

如果您是创建一个图书馆,在那里你期望一个巨大的字符串在你的函数传递,无论是定义一个参数作为一个StringBuilder或流。

此外,字符串的方式实现(每个平台不同),当你开始一起将它们订。就像使用StringBuilder。它allocats一个缓冲区,供您复制进去,一旦你到达终点,它分配给你,甚至更多的内存,在希望,如果你做一个大的连接性能不会受到阻碍。

也许乔恩斯基特可以帮助了在这里?

它主要性能问题。

有串表现得像在编写代码时,而拥有它是值类型将作出巨大的性能击中值类型的帮助。

有关的深入了解,采取偷看在好的文章上字符串在.NET框架。

你怎么能告诉string是引用类型?我不知道它的问题是如何实现的。在C#中的字符串是不可变的正是这样你就不必担心这个问题。

其实弦已经很少相似之处值类型。对于初学者来说,并不是所有的值类型是不可改变的,你可以改变你想要一个Int32值,它仍然会在堆栈上相同的地址。

字符串是不可变的一个很好的理由,它有什么用它做是引用类型,但有很多事情要做内存管理。这只是更有效地创建一个新的对象时,字符串大小的变化,而不是在托管堆上东西游移。我觉得你值/引用类型和不可变对象的概念混合在一起。

据“==”:就像你说的“==”是一个操作符重载,再次它是一个很好的理由让框架处理字符串的时候比较有用实施

在一个非常简单的话谁具有明确尺寸的任何值可以被视为一个值类型。

作为字符串被由字符阵列的不只是简单。我看字符串作为字符数组[]。因此,它们是在堆上因为参考存储器位置存储在栈,并指向在堆上阵列的存储器的开始位置上。之前被分配......完美的堆字符串大小是不知道。

这就是为什么一个字符串是真的一成不变的,因为当你改变它,即使是同尺寸的编译器不知道这一点,必须分配一个新的数组,并指定字符数组中的位置。这是有道理的,如果你认为字符串作为一种方式,语言保护您不必在飞行中分配内存(READ C类编程)

在得到另一个神秘反对票的风险......实际上很多提栈和内存相对于值类型和原始类型,是因为他们必须适应在微处理器中的寄存器。您无法推送或弹出的东西向/从,如果它需要更多的比特比寄存器具有堆栈....所述指令,例如“弹出EAX” - 因为EAX 32个位宽为32位的系统上

浮点原语类型由FPU,这是宽80位来处理。

这是所有决定长之前有一个OOP语言混淆基本类型的定义和我假定值类型是已经为OOP语言专门创建的术语。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top