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

Array in C# are reference type, why they acts as a value types?

根据 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

Arrays are mechanisms that allow you to treat several items as a single collection. The Microsoft® .NET Common Language Runtime (CLR) supports single-dimensional arrays, multidimensional arrays, and jagged arrays (arrays of arrays). All array types are implicitly derived from System.Array, which itself is derived from System.Object. This means that all arrays are always reference types which are allocated on the managed heap, and your app's variable contains a reference to the array and not the array itself.

你的问题与数组无关。由于您的 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

写入 t2 = "Three" 不会改变 t1 的值,因为类型是引用类型,所以它们 "point" 到它们的数据。通过分配给 t2 你告诉它引用别的东西。

Liukewise,当您写 t2 = t1 时,您只是告诉 t2 引用与 t1 相同的内容。未来对 t2 的分配只会使其引用其他内容。

某些语言(如 C++)确实能够让您存储对另一个变量的引用,因此当您更改引用时,您实际上更改了另一个变量的内容。

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

var t1 = data[0];

您已声明一个新变量 t1,它引用与 data[0] 相同的字符串。在这之后你写:

var t2 = t1;

现在您有一个新变量 t2,它引用与 t1 相同的字符串。您现在在堆上有一个 String 对象,以及对该对象的三个引用:data[0]t1t2.

然后你写:

t2 = "Three";

在这条语句之后,t2 指向堆中另一个字符串,值为 "Three"。但是,data[0]t1 仍然指向相同的原始字符串。

这个程序完全符合您的预期。

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 ;
}

一图抵一千字,所以是这样的:

"Three"赋值给t2的效果是赋值前t1t2引用了同一个对象,赋值后引用了不同的对象对象。这里没有其他事情发生。

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

when you assign one array reference variable to another, you are simply making both variables refer to the same array. You are neither causing a copy of the array to be created, nor are you causing the contents of one array to be copied to the other.

// Assigning array reference variables.

        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