C#中的数组是引用类型,为什么它们作为值类型?

nun*_*unu 6 .net c# arrays c#-4.0

根据MSDN,如果所有数组都是引用类型,那么为什么在给定的示例代码中,新值t2不反映变化t1

string[] data = new[] { "One", "Two" };

var t1 = data[0];

Console.WriteLine(t1);

var t2 = t1;
t2 = "Three"; //assigning the new value, and this should reflect in t1

Console.WriteLine(t2);
Console.WriteLine(t1); // this should print 'Three', but it prints 'One'

Console.Read();
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

http://msdn.microsoft.com/en-us/magazine/cc301755.aspx

数组是允许您将多个项目视为单个集合的机制.Microsoft®.NET公共语言运行库(CLR)支持单维数组,多维数组和锯齿状数组(数组数组).所有数组类型都是从System.Array隐式派生的,System.Array本身派生自System.Object.这意味着所有数组始终是在托管堆上分配的引用类型,并且应用程序的变量包含对数组的引用,而不是数组本身.

das*_*ght 19

一张图片胜过千言万语,所以这是正在发生的事情:

之前和之后

的分配的效果"Three"t2的是,分配之前t1t2引用的相同的对象,但在转让之后它们引用不同的对象.这里没有其他任何事情发生.

如果你有一组可变对象,并且操纵它们的值而不是设置它们的引用,情况会有所不同.例如,假设用一个StringBuilder对象数组替换字符串数组,并调用t2.Replace("Two", "Three")而不是赋值.现在的效果是不同的,因为t1,t2以及data[0]将指向同一个对象.

  • 不需要1000个单词,只需要这些:OP代码中唯一的数组是`data`,它从不使用,除了拔出它的第0个元素. (2认同)

Son*_*nül 8

你的问题与数组无关.既然你data[0]string- 并且它是一个参考类型 - 它的价值在于One,你永远不会改变它的价值.您刚刚创建了另一个名为的字符串引用,t2并通过t1引用将其指向同一个对象.将此引用对象更改为后"Three",但这不会影响t1引用的内容.

让我们逐行看看你的代码;

var t1 = data[0];
Run Code Online (Sandbox Code Playgroud)

使用此行,您创建了一个字符串引用,t1并指向"One"对象.

var t2 = t1;
Run Code Online (Sandbox Code Playgroud)

有了这条线,你新建一个字符串作为参考t2,这指向同一个对象与t1"One"

t2 = "Three";
Run Code Online (Sandbox Code Playgroud)

使用此行,您将创建一个名为的字符串对象,"Three"并且您t2将引用此对象.它不再指向"One"对象.但这并不影响t1参考.它仍然指向"One"对象.

这就是为什么

Console.WriteLine(t2);
Console.WriteLine(t1);
Run Code Online (Sandbox Code Playgroud)

版画

Three
One
Run Code Online (Sandbox Code Playgroud)


Eli*_*ing 7

字符串也是引用类型.所以,如果你写:

var t1 = data[0];
Run Code Online (Sandbox Code Playgroud)

您已声明一个t1引用相同字符串的新变量data[0].在此之后你写道:

var t2 = t1;
Run Code Online (Sandbox Code Playgroud)

现在你有了一个t2引用相同字符串的新变量t1.你现在有一个String堆上对象和三个引用到这个对象:data[0],t1t2.

然后你写:

t2 = "Three";
Run Code Online (Sandbox Code Playgroud)

在此语句之后,t2指向堆中带有值的antoher字符串"Three".然而,data[0]t1仍然指向相同的原始字符串.