sel*_*raj 7 c# string reference-type primitive-types
为什么string是引用类型,即使它通常是原始数据类型,如int,float或double.
Eri*_*ert 18
除了Dan发布的原因:
根据定义,值类型是那些将值存储在自身中的类型,而不是在其他地方引用值.这就是为什么值类型被称为"值类型",而引用类型被称为"引用类型".所以你的问题实际上是"为什么字符串引用其内容而不是简单地包含其内容?"
这是因为值类型具有nice属性,即给定值类型的每个实例在内存中具有相同的大小.
所以呢?为什么这是一个不错的财产?好吧,假设字符串是可以是任何大小的值类型,请考虑以下内容:
string[] mystrings = new string[3];
Run Code Online (Sandbox Code Playgroud)
三个字符串数组的初始内容是什么?值类型没有"null",因此唯一明智的做法是创建一个包含三个空字符串的数组.怎么会在记忆中被列出来?想一想.你会怎么做?
现在假设你说
string[] mystrings = new string[3];
mystrings[1] = "hello";
Run Code Online (Sandbox Code Playgroud)
现在我们在数组中有"","hello"和"".内存在哪里"你好"去了吗? 分配给mystrings [1]的插槽有多大?数组及其元素的内存必须在某处.
这使CLR有以下选择:
CLR团队选择了后者.将字符串转换为引用类型意味着您可以有效地创建它们的数组.
Dan*_*Tao 10
哎呀,这个答案得到了接受,然后我改变了.我应该在底部包括原始答案,因为这是OP所接受的.
更新:这就是事情.string 绝对需要表现得像一个引用类型.到目前为止,所有答案都触及了这个原因:string类型没有常量大小,将字符串的全部内容从一个方法复制到另一个方法是没有意义的,string[]否则数组必须调整主题大小 -仅举几个.
但是你仍然可以定义 string为struct内部指向一个char[]数组甚至一个char*指针,并指出int它的长度,使它成为不可变的,瞧!,你有一个行为类似于引用类型但在技术上是值类型的类型.
老实说,这看起来很傻.正如Eric Lippert在其他答案的一些评论中指出的那样,定义这样的值类型与定义引用类型基本相同.几乎在所有意义上,它都与以相同方式定义的引用类型无法区分.
那么问题的答案"为什么是string参考类型?" 基本上是:"让它成为一种价值类型只会是愚蠢的." 但是,如果这是唯一的原因,那么,合乎逻辑的结论是,string实际上可以将其定义为struct如上所述,并且对于该选择没有特别好的论据.
然而,有原因,它是更好地使string一个class比一个struct是比纯粹的智力了.这是我能想到的一对夫妇:
如果string是一个值类型,那么每当你将它传递给某个方法时,object它就必须装箱,这会产生一个新的object,这会使堆膨胀并导致无意义的GC压力.由于琴弦基本上无处不在,让它们一直引起装箱将是一个大问题.
是的,无论是引用类型还是值类型,string都可以覆盖Equals.但如果它是一个值类型,那么ReferenceEquals("a", "a")将返回false!这是因为两个参数都会被装箱,并且盒装参数永远不会有相同的引用(据我所知).
因此,即使你可以定义一个值类型,使其像一个引用类型一样,它由一个引用类型字段组成,但它仍然不完全相同.所以我认为这是一个更完整的原因,为什么string是一个引用类型:你可以使它成为一个值类型,但这只会带来不必要的弱点.
它是一个引用类型,因为只传递对它的引用.
如果它是值类型,则每次将字符串从一个方法传递到另一个方法时,整个字符串将被复制*.
因为它是一个引用类型,而不是像"Hello world!"这样的字符串值.传递 - "你好世界!" 顺便说一下,它是12个字符,这意味着它需要(至少)24个字节的存储空间 - 只传递对这些字符串的引用.传递引用比传递字符串中的每个字符要便宜得多.
而且,它实际上不是普通的原始数据类型.谁告诉你的?
*实际上,这并不严格.如果字符串内部拥有一个char[]数组,那么只要数组类型是引用类型,字符串的内容实际上就不会通过值传递 - 只有对数组的引用才是.不过,我仍然认为这基本上是正确的答案.