[英]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
是在賦值t1
和t2
引用相同對象之前,但在賦值之后它們引用不同的對象。 這里沒有其他任何事情發生。
如果你有一組可變對象,並且操縱它們的值而不是設置它們的引用,情況會有所不同。 例如,假設用StringBuilder
對象數組替換字符串數組,並調用t2.Replace("Two", "Three")
而不是賦值。 現在效果會有所不同,因為t1
, t2
和data[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]
, t1
和t2
。
然后你寫:
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.