3
object[] objs = new object[]{"one","two","three"};

存储在数组中的字符串是否作为对字符串对象的引用

[@] - one
[@] - two
[@] - three

还是字符串对象存储在数组元素中?

[one][two][three]

谢谢。

编辑:对不起,我的精美图表惨遭失败。

4

4 回答 4

5

字符串对象永远不能直接存储在数组中,也不能作为任何其他变量存储。它总是引用,即使在简单的情况下,例如:

string x = "foo";

这里的值x是一个引用,而不是一个对象。没有表达式值永远是对象——它总是一个引用、一个值类型值或一个指针。

于 2012-06-16T22:48:22.517 回答
4

Jon Skeet 很好地描述了实际的实现,但让我们考虑一下为什么 CLR 将字符串直接存储在数组中是荒谬的。

第一个原因是直接在数组中存储字符串会损害性能。如果字符串直接存储在数组中,那么为了到达数组的元素 1000,CLR 必须遍历数组中所有字符串的字节,直到到达元素 1000,并一直检查字符串边界。由于字符串和任何其他引用类型作为引用存储在数组中,因此找到数组的正确元素需要一次乘法、一次加法和跟随一个指针(这里指针的概念是在实现级别,而不是程序员可见等级)。这会产生更好的性能。

字符串不能合理地直接存储在数组中的第二个原因是引用类型的 C# 数组是协变的。假设字符串直接存储在生成的数组中

string[] strings = new string[] {"one", "two", "three"};

然后,你把它转换成一个对象数组,这是合法的

object[] objs = (object[])strings;

编译器应该如何生成考虑到这种可能性的代码?将对象数组作为参数的方法可以将字符串数组传递给它,因此 CLR 需要知道是将数组作为对象数组、字符串数组还是其他类型的数组进行索引。不知何故,在运行时,每个数组都必须用数组的类型声明进行标记,并且每个数组访问都必须检查类型声明,然后根据数组的类型以不同的方式遍历数组。坚持使用引用要简单得多,它允许数组访问的单一实现并提高启动性能。

于 2012-06-16T23:01:37.150 回答
2

它们作为参考存储在内部。存储了字符串的副本,并且在使用该字符串的任何地方,都有对相同存储字符串的引用。(这是字符串不可变的众多原因之一;否则,修改字符串的一个实例会修改它出现的任何地方)

于 2012-06-16T22:48:11.773 回答
1

所有原始类型都直接存储到数组中,但所有其他对象或引用类型都存储为内存引用。对于不限于字符串的所有对象都是如此。

于 2012-06-16T22:57:52.897 回答