根据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();
http://msdn.microsoft.com/en-us/magazine/cc301755.aspx
数组是一种机制,允许您将多个项目视为一个 单一集合。 Microsoft®.NET公共语言运行时(CLR) 支持一维数组,多维数组和 锯齿状数组(数组数组)。所有数组类型都是隐式的 派生自System.Array,它本身派生自System.Object。 这意味着所有数组都是引用类型 在托管堆上分配,您的应用程序的变量包含一个 引用数组而不是数组本身。
答案 0 :(得分:18)
一张图片胜过千言万语,所以这是正在发生的事情:
"Three"
到t2
的分配效果是在赋值t1
和t2
之前引用相同的对象,但在赋值之后它们引用了不同的对象。这里没有其他任何事情发生。
如果你有一个可变对象数组,并且操纵它们的值而不是设置它们的引用,情况会有所不同。例如,假设用一组StringBuilder
个对象替换字符串数组,并调用t2.Replace("Two", "Three")
而不是赋值。现在效果会有所不同,因为t1
,t2
和data[0]
会指向同一个对象。
答案 1 :(得分:8)
您的问题与数组无关。由于您的data[0]
为string
- 并且它是引用类型 - 它的值为One
,因此您永远不会更改它的值。您刚刚创建了另一个名为t2
的字符串引用,并使用t1
引用将其指向同一个对象。将此引用对象更改为"Three"
后,但这不会影响t1
引用的内容。
让我们逐行查看您的代码;
var t1 = data[0];
使用此行,您创建了一个字符串引用t1
,这指向"One"
对象。
var t2 = t1;
使用此行,您可以创建一个新的字符串引用t2
,并指向t1
"One"
的同一个对象
t2 = "Three";
使用此行,您将创建一个名为"Three"
的字符串对象,并且您的t2
将引用此对象。它不再指向"One"
对象 。但是这个不会影响t1
引用。 仍然指向"One"
对象。
这就是为什么
Console.WriteLine(t2);
Console.WriteLine(t1);
打印
Three
One
答案 2 :(得分:7)
字符串也是引用类型。所以,如果你写:
var t1 = data[0];
您已声明一个新变量t1
,该变量引用与data[0]
相同的字符串。在此之后你写道:
var t2 = t1;
现在您有了一个新变量t2
,它引用了与t1
相同的字符串。您现在在堆上有一个String
对象,以及对该对象的三个引用:data[0]
,t1
和t2
。
然后你写:
t2 = "Three";
在此语句之后,t2
指向堆中具有值"Three"
的antoher字符串。但是,data[0]
和t1
仍然指向相同的原始字符串。
答案 3 :(得分:0)
写t2 = "Three"
不会改变t1的值,因为类型是引用类型,所以它们"指向"他们的数据。通过分配给t2
,您可以告诉它引用其他内容。
Liukewise,当你写t2 = t1
时,你只是告诉t2
引用与t1
相同的内容。对t2
的未来分配只会使其引用其他内容。
某些语言(如C ++)确实能够存储对其他变量的引用,因此当您更改引用时,实际上会更改其他变量的内容。
答案 4 :(得分:0)
这个程序完全符合您的预期。
void Main()
{
abc[] data = new[] { new abc(){i=1}, new abc(){i=2} };
var t1 = data[0];
var t2 = t1;
// here is the difference
// t2 is still pointing to its old location
// but i will point a new position.
t2.i = 5 ; //assigning the new value to i
// but t2 still pointing to t1
//all will be identical now.
Console.WriteLine(t2);
Console.WriteLine(t1);
Console.WriteLine(data[0]);
// repeating like you.
t2 = new abc() {i=444};
//now you will see t2 is different form t1. because
// now t2 pointing to a new object instead of t1.
Console.WriteLine(t2);
Console.WriteLine(t1);
}
public class abc{
public int i ;
}
答案 5 :(得分:-1)
当你将一个数组引用变量分配给另一个时,你就是 简单地让两个变量都引用同一个数组。你不是 导致创建数组的副本,也不会导致 要复制到另一个数组的一个数组的内容。
//分配数组引用变量。
using System; class AssignARef {
static void Main()
{
int i;
int[] nums1 = new int[10];
int[] nums2 = new int[10];
for(i=0; i < 10; i++)
nums1[i] = i;
for(i=0; i < 10; i++)
nums2[i] = -i;
Console.Write("Here is nums1: ");
for(i=0; i < 10; i++)
Console.Write(nums1[i] + " ");
Console.WriteLine();
Console.Write("Here is nums2: ");
for(i=0; i < 10; i++)
Console.Write(nums2[i] + " ");
Console.WriteLine(); nums2 = nums1; // now nums2 refers to nums1
Console.Write("Here is nums2 after assignment: ");
for(i=0; i < 10; i++)
Console.Write(nums2[i] + " ");
Console.WriteLine(); // Next, operate on nums1 array through nums2.
nums2[3] = 99;
Console.Write("Here is nums1 after change through nums2: ");
for(i=0; i < 10; i++)
Console.Write(nums1[i] + " ");
Console.WriteLine();
}
}
O / P
Here is nums1: 0 1 2 3 4 5 6 7 8 9
Here is nums2: 0 -1 -2 -3 -4 -5 -6 -7 -8 -9
Here is nums2 after assignment: 0 1 2 3 4 5 6 7 8 9
Here is nums1 after change through nums2: 0 1 2 99 4 5 6 7 8 9