2014-10-30 106 views
0

見=
我需要的是一個==
不只是返回true - !是同一個對象Deepclone - 傳遞給構造函數對象不再==

如果我改變MyObj1.MyRepeat的變化也是MyObj2.MyRepeat
如果我改變MyObj1Clone.MyRepeat它不會改變MyObj2Clone.MyRepeat(或MyObj1.MyRepeat)

肯定我只需要編寫一個CustomClone,而不是用這個序列化/反序列化DeepClone
只是檢查 - 是否有另一種方式?

MyRepeatedObj MyRepeat = new MyRepeatedObj("xxx"); 

MyObj MyObj1 = new MyObj (1, MyRepeat); 
MyObj MyObj2 = new MyObj (2, MyRepeat); 

// MyObj1.MyRepeat == MyObj2.MyRepeat 

MyObj MyObj1Clone = DeepClone(MyObj1); 
MyObj MyObj2Clone = DeepClone(MyObj2); 

// MyObj1Clone.MyRepeat != MyObj2Clone.MyRepeat 


public static T DeepClone<T>(T obj) 
{ 
    using (var ms = new MemoryStream()) 
    { 
     var formatter = new BinaryFormatter(); 

     formatter.Serialize(ms, obj); 
     ms.Position = 0; 

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

正如漢斯建議我介紹一個GUID的PK和使用,對於重寫equals
.Equal返回true
==仍是假的,因爲它似乎DeepCone創建單獨的對象

public Guid PK { get { return guid; } } 
public override bool Equals(Object obj) 
{ 
    // Check for null values and compare run-time types. 
    if (obj == null) return false; 
    if (!(obj is SearchEnum1MVand)) return false; 
    SearchEnum1MVand comp = (SearchEnum1MVand)obj; 
    return (comp.PK == this.PK); // && comp.AndOr == this.AndOr 
} 
public override int GetHashCode() 
{ 
    return FieldDef.ID; 
} 

我很抱歉沒有在第一篇文章中包含更多細節

public MyRepeatedObj(GabeLib.FieldDefEnum1 FieldDef, GabeLib.enumAndOr paramAndOr) 
{ 
    // the si... are MyObj that I pass the reference with this 
    siAll = new SearchItemEnum1(paramAndOr, enumSrchCond.All, FieldDef, this); 
    siAllNot = new SearchItemEnum1(paramAndOr, enumSrchCond.Not_All, FieldDef, this); 
    siAny = new SearchItemEnum1(paramAndOr, enumSrchCond.Any, FieldDef, this); 
    siAnyNot = new SearchItemEnum1(paramAndOr, enumSrchCond.Not_Any, FieldDef, this); 

當我seria麗澤/反序列化是4個不同的這種

但我序列化/反序列化4個MyObj中 - 我會嘗試序列化/反序列化MyRepeatedObj然後拿到4 MyObj中作爲屬性

DeepClone在MyRepeatedObj固定它

SearchEnum1MVand searchEnum1MVand = DeepClone<SearchEnum1MVand>(((SearchItemEnum1)fieldDefSSDrowSelected.SearchItems[0]).SearchEnum1MVand); 
Debug.WriteLine(searchEnum1MVand.SIall.SearchEnum1MVand.MVid.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.SearchEnum1MVand.MVid.ToString()); 
searchEnum1MVand.SIall.SearchEnum1MVand.MVid++; 
Debug.WriteLine(searchEnum1MVand.SIall.SearchEnum1MVand.MVid.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.SearchEnum1MVand.MVid.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIall.EnterOrder.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.EnterOrder.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.SearchEnum1MVand.SIall.EnterOrder.ToString()); 
searchEnum1MVand.SIall.EnterOrder++; 
Debug.WriteLine(searchEnum1MVand.SIall.EnterOrder.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.EnterOrder.ToString()); 
Debug.WriteLine(searchEnum1MVand.SIany.SearchEnum1MVand.SIall.EnterOrder.ToString()); 
+2

我的水晶球說,你忘了重寫GetHashCode()。所以,你得到的Object.GetHashCode()的返回值,不同的價值觀,因爲它們是不同的對象。 – 2014-10-30 20:46:45

+0

@HansPassant我把重寫GetH ashCode()返回並且它們仍然不相等。我曾經重寫GetHashCode()和Equals,它的工作原理,但我不能再覆蓋Equals,因爲對象不再有PK。 – Paparazzi 2014-10-31 12:20:05

+0

好吧,你確實做錯了,但我們看不到你做錯了。無論如何,散列幾乎不適用於主鍵,它不保證是唯一的。如果你需要一個PK,那就把它變成一個屬性。 Guid總是一個好主意。 – 2014-10-31 12:25:57

回答

2

==仍然是假,因爲它出現DeepCone創建單獨的對象

嗯,是的 - 如果它返回相同的對象,它不會是一個「克隆」!

Deserialization總是創建新對象。如果你想要一個新的父對象,但保留對子對象的引用,那麼你想要一個淺的克隆。有幾個選項來做到這一點:

  • 添加Clone()方法MyObj調用this.MemberwiseClone();(你不能在外部,因爲它是protected而不是public調用它通過字段和屬性
  • 使用反射來循環。 。將它們複製到新的對象
+0

請再次閱讀該問題。對同一對象的引用不再是對同一對象的引用。 MyObj1.MyRepeat == MyObj2.MyRepeat和MyObj1Clone.MyRepeat!= MyObj2Clone.MyRepeat。愚弄它返回一個真正的不會使它成爲同一個對象,我需要它是同一個對象。編寫一個MyClone並不是什麼大不了的事情。我只是將所有參加課程的人都加入到課堂作爲輸入。 – Paparazzi 2014-10-31 13:37:52

+0

好的是的我誤解了你的問題 - 你想要的是一個_shallow_克隆。 – 2014-10-31 14:10:13

+0

對不起,問題不明確。我可能會使用錯誤的術語,但我認爲我仍然需要深入複製。我需要一個新的MyObj1Clone和MyObj2Clone以及它們都引用的新MyRepeatedObj。 – Paparazzi 2014-10-31 14:18:11