2011-07-25 40 views
3

所以我今天發現,當用C#中的變量賦值時,結構和類的行爲是不同的。這是我的理解,當我將一個結構賦值給一個變量,變量存儲該結構的一個副本,並且當我將一個類分配給一個變量時,該變量存儲對該類實例的引用。C#與struct中的列表混淆(值類型與引用類型)

在這種情況下,dad2包含dad1的副本,所以不應該對dad2做任何事情而不會影響dad1?顯然不是這樣的,因爲當我給爸爸添加一個兒子時,它也爲爸爸添加了同一個兒子。

public struct Dad { 
     public string name; 
     public List <Son> sons; 

     public struct Son { 
      public string name; 

      public Son (string n) { 
       name = n; 
      } 
     } 
    } 

    static void Main (string [] args) { 
     Dad dad1 = new Dad(); 
     dad1.name = "Bob"; 
     dad1.sons = new List <Dad.Son> {new Dad.Son ("A")}; 

     Dad dad2 = dad1; 
     Debug.WriteLine (dad2.Equals (dad1) + " " + dad1.sons.Count() + " " + dad2.sons.Count()); 
     //true 1 1 
     dad2.sons.Add (new Dad.Son ("B")); 
     Debug.WriteLine (dad2.Equals (dad1) + " " + dad1.sons.Count() + " " + dad2.sons.Count()); 
     //true 2 2 
    } 

回答

3

是它使得結構內的值的副本 - 和結構有一個列表的引用,以便引用被複制過內 - 這是一個「淺拷貝」 ......如果名單將已經被複制到一個新的對象,這將是一個「深拷貝」 ...... 結構分配使用「複製」語義取決於每個成員的複製語義......看到http://msdn.microsoft.com/en-us/library/saxz13w4.aspx

+0

我明白了,所以在宣佈dad2之後,我必須重新聲明其List並從dad1的List中複製元素。 – TreeTree

1

想想類類型的變量和字段作爲舉行「實例ID的」,一切都將清晰。假設List類型的結構字段「Foo」的值爲「實例ID#95341」。複製結構將產生另一個結構,其字段「Foo」也包含「實例ID#95341」。在一個這樣的結構上調用Foo.Add將會在「實例ID#95341」引用的列表中添加一個元素。在另一個這樣的結構中查詢Foo.Count會從「實例ID#95341」引用的列表中獲得計數,這自然會是相同的List。