2014-01-29 31 views
3

我有一個有趣的問題。我有一類人:添加到Observable Collection時的奇怪行爲

public class Person 
    { 
     public string Name { get; set; } 
     public int? Score { get; set; } 
     public int NbrOfWins { get; set; } 
     public int NbrOfLosses { get; set; } 
     public int HighScore { get; set; } 
    } 

我創建一個觀察的集合:

ObservableCollection<Person> test = new ObservableCollection<Person>(); 

我有一個擴展方法添加到觀察集合:

public static void myFillTest<T>(this ObservableCollection<T> value1, T value2, int nbr) 
     { 
      for (int x = 0; x < nbr; x++) 
      { 
       value1.Add(value2); 
      } 
     } 

我加5項像這樣的集合:

test.myFillTest(new Person { Name = "None" }, 5); 

如果我更改了一個實例名稱:

test[2].Name = "John"; 

所有在收集變化的項目,因爲如果他們都指向同一件事。 這將是什麼原因?順便說一下,這適用於類型爲int的字符串和字符串,但不適用於typeof類。

+0

要添加相同的參考(值2)。添加值類型時,它可以工作,因爲它們不是引用。 –

+1

正如使用nbr作爲參數名稱一樣令人困惑。你應該寫你的變量名,這樣如果你閱讀你的代碼(或其他人),他們將很容易知道是什麼。更好的辦法是使用「int numberofcopies」,然後你的代碼立即更具可讀性。 value1和value2也不是很具描述性。 – TylerD87

回答

4

這是因爲Person類是引用類型,而整數是值類型。當你添加5次相同的int時,它被複制,當你添加5次人時,它的一個實例被添加到5個不同的索引中。您可以在這裏閱讀有關參考類型http://msdn.microsoft.com/en-us/library/490f96s2.aspx。如果您希望按預期工作,則需要複製類型爲person的對象。

你可以改變你的代碼如下,以隨時創建新的對象:

public static void MyFillTest<T>(this ObservableCollection<T> value1, T value2, int nbr) 
{ 
    for (int x = 0; x < nbr; x++) 
    { 
     if (typeof(T).IsValueType) 
     { 
      value1.Add(value2); 
     } 
     else 
     { 
      if (value2 is ICloneable) 
      { 
       ICloneable cloneable = (ICloneable)value2; 
       value1.Add((T)cloneable.Clone()); 
      } 
     } 
    } 
} 

public class Person : ICloneable 
{ 
    public string Name { get; set; } 
    public int? Score { get; set; } 
    public int NbrOfWins { get; set; } 
    public int NbrOfLosses { get; set; } 
    public int HighScore { get; set; } 

    #region ICloneable Members 

    public object Clone() 
    { 
     return new Person 
     { 
      Name = this.Name, 
      Score = this.Score, 
      NbrOfWins = this.NbrOfWins, 
      NbrOfLosses = this.NbrOfLosses, 
      HighScore = this.HighScore 
     }; 
    } 

    #endregion 
} 
+0

謝謝你給出了一個很好的答案,我一直在思考這些問題,而且這個工作很棒! –

2

當您調用您的方法時,新人{Name =「None」}僅實例化一次。所以他們都參考同一個對象。

2

它很簡單 - 要添加value2到集合nbr倍。或者更確切地說,當添加一個對象時(如同您在示例中),您正在向同一對象nbr次添加參考。所以,如果你改變它,你可以改變它們。

0

Person對象被實例化一次,其引用被使用5次。你可以通過使用成員副本來創建原始對象的淺拷貝來克服這個問題。

1

這個擴展方法做你正在嘗試做的:

public static void myFillTest<T>(this ObservableCollection<T> value1, Action<T> init, int nbr) where T: new() 
{ 
    for (int x = 0; x < nbr; x++) 
    { 
     var value2 = new T(); 
     init(value2); 

     value1.Add(value2); 
    } 
} 

這樣稱呼它:

test.myFillTest(p => p.Name = "None", 5); 
相關問題