簡體   English   中英

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

數組是允許您將多個項目視為單個集合的機制。 Microsoft®.NET公共語言運行庫(CLR)支持單維數組,多維數組和鋸齒狀數組(數組數組)。 所有數組類型都是從System.Array隱式派生的,System.Array本身派生自System.Object。 這意味着所有數組始終是在托管堆上分配的引用類型,並且應用程序的變量包含對數組的引用,而不是數組本身。

一張圖片勝過千言萬語,所以這是正在發生的事情:

之前和之后

賦值"Three"t2是在賦值t1t2引用相同對象之前,但在賦值之后它們引用不同的對象。 這里沒有其他任何事情發生。

如果你有一組可變對象,並且操縱它們的值而不是設置它們的引用,情況會有所不同。 例如,假設用StringBuilder對象數組替換字符串數組,並調用t2.Replace("Two", "Three")而不是賦值。 現在效果會有所不同,因為t1t2data[0]將指向同一個對象。

你的問題與數組無關。 由於您的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

字符串也是引用類型。 所以,如果你寫:

var t1 = data[0];

您已聲明一個新變量t1 ,它引用與data[0]相同的字符串。 在此之后你寫道:

var t2 = t1;

現在你有了一個新的變量t2 ,它引用了與t1相同的字符串。 現在,堆上有一個String對象,以及對該對象的三個引用: data[0]t1t2

然后你寫:

t2 = "Three";

在此語句之后, t2指向堆中的antoher字符串,值為"Three" 但是, data[0]t1仍然指向相同的原始字符串。

寫入t2 = "Three"不會改變t1的值,因為類型是引用類型,因此它們“指向”它們的數據。 通過分配給t2你告訴它引用別的東西。

Liukewise,當你寫t2 = t1你只是告訴t2引用與t1相同的東西。 未來對t2任務只會讓它引用別的東西。

某些語言(如C ++)確實能夠存儲對其他變量的引用,因此當您更改引用時,實際上會更改其他變量的內容。

這個程序完全符合您的預期。

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

當您將一個數組引用變量分配給另一個時,您只需使兩個變量引用相同的數組。 您既不會創建要創建的數組的副本,也不會導致將一個數組的內容復制到另一個數組。

//分配數組引用變量。

        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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM