2015-08-24 89 views
0

我正在使用C#,.Net 4.0,並且我想做一個簡單的任務來複制字典中的Item(顯然有不同的關鍵字)。在字典中修改複製的數據會修改原始文件

我遇到了一些問題。

當我做最初的副本時,我沒有任何問題。當我更改副本的值時,原件的值也會更改。爲什麼是這樣?

private void CopyItem(Guid newItemKey, Guid oldItemKey) 
{  
    this.dictionary[newItemKey] = this.dictionary[oldItemKey]; 
    this.dictionary[newItemKey].Id = newItemKey; 
} 

// this.dictionary[oldItemKey].Id is now equal to newItemKey... Why? 

我也曾嘗試:

private void CopyItem(Guid newItemKey, Guid oldItemKey) 
{  
    var value = this.dictionary[oldItemKey]; 
    value.Id = newItemKey; 
    this.dictionary[newItemKey] = value; 
} 

// this.dictionary[oldItemKey].Id is now equal to newItemKey... Why? 

我仍然得到同樣的結果。

+2

推測字典包含一些引用類型。你需要[閱讀此](http://www.albahari.com/valuevsreftypes.aspx)。 [也是這個](http://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in​​-c) –

+4

什麼是項目?如果它是一個引用類型,那麼你沒有創建該項目的副本,你正在複製該引用,它們都引用同一個對象。 –

+2

問題的確是這兩個值只是對同一個對象的引用。 **我**會問的問題是您爲什麼要複製東西?你幾乎從不想在任何程序中這樣做,因爲這是一個讓你頭痛的難題。很可能,你正在考慮一個問題的錯誤解決方案。 – MarioDS

回答

3

您並未創建副本。您正在使用相同的項目,只是對它的不同參考。爲了複製引用類型,您必須使用關鍵字new,並將新對象的所有屬性設置爲與舊對象相同。如果您持有引用類型的源代碼,則還可以實施ICloneable

Your code should look something like : 

    private void CopyItem(Guid newItemKey, Guid oldItemKey) 
    {  
     // Assuming you implemented ICloneable.. 
     this.dictionary[newItemKey] = this.dictionary[oldItemKey].Clone(); 

     this.dictionary[newItemKey].Id = newItemKey; 
    } 
3

這是因爲如果你的字典持有引用類型的值,你會不會複製該引用類型值,而是你只是重新分配它。所以,如果你開始喜歡這個

[key1][reference_to_0x008B] 

一個dictionalry和你的字典值複製到另一個關鍵,它只會複製自身導致以下字典參考:

[key1][reference_to_0x008B] 
[key2][reference_to_0x008B] 

所以你」會看到參考指向您的記憶中同一個對象位於兩個鍵的某個位置。之後操作對象,之後您將得到這兩個鍵的修改。

總之:被引用的對象不會被自動克隆,它只是指向它的指針。所以你必須自己完成一個副本,但這可能非常棘手(取決於你的需求) - 例如this article

1

您需要克隆字典,因爲引用指向相同的內存位置,請參閱以下文章以瞭解執行此操作的方法。

What is the best way to clone/deep copy a .NET generic Dictionary<string, T>?

以下報價是喬恩給

public static Dictionary<TKey, TValue> CloneDictionaryCloningValues<TKey, TValue> 
    (Dictionary<TKey, TValue> original) where TValue : ICloneable 
{ 
    Dictionary<TKey, TValue> ret = new Dictionary<TKey, TValue>(original.Count, 
                 original.Comparer); 
    foreach (KeyValuePair<TKey, TValue> entry in original) 
    { 
     ret.Add(entry.Key, (TValue) entry.Value.Clone()); 
    } 
    return ret; 
} 
0

目前,當你複製的對象,它是淺拷貝的答案之一,就是這個道理,

,如果您需要對引用對象(例如類)進行深度拷貝,您可以按照以下方式編寫您的克隆函數來實現它。

public static T DeepCloneCopy<T>(T obj) 
    { 
     using (var ms = new MemoryStream()) 
     { 
      var formatter = new BinaryFormatter(); 
      formatter.Serialize(ms, obj); 
      ms.Position = 0; 

      return (T)formatter.Deserialize(ms); 
     } 
    }