【发布时间】:2014-12-27 01:19:38
【问题描述】:
查看 !=
我需要那是一个 ==
不只是返回 true - 是同一个对象
如果我更改 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);
}
}
按照 Hans 的建议,我将 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);
当我序列化/反序列化时,这是 4 种不同的
但我序列化/反序列化 4 MyObj - 我将尝试序列化/反序列化 MyRepeatedObj,然后将 4 MyObj 作为属性
MyRepeatedObj 的 DeepClone 修复了它
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());
【问题讨论】:
-
我的水晶球说你忘记覆盖 GetHashCode()。所以你得到了 Object.GetHashCode() 返回的值。不同的值,因为它们是不同的对象。
-
@HansPassant 我把 override GetHashCode() 放回去,它们仍然不相等。我曾经覆盖 GetHashCode() 和 Equals 并且它有效,但我不能再覆盖 Equals,因为该对象不再具有 PK。
-
好吧,你肯定做错了,但我们看不到你做错了。无论如何,散列几乎永远不适合主键,它不能保证是唯一的。如果您需要 PK,那么只需将其设为属性即可。 Guid 总是一个好主意。
-
@HansPassant 我没有做错。 MyObj1Clone.MyRepeat MyObj2Clone.MyRepeat 现在具有相同的哈希值,但仍然不相等。我没有说我使用散列作为 PK - 我说对象不再具有自然 PK。 GUID 可能会解决这个问题,但它仍然会留下另一个问题。我将测试 GUID 是否相等,因为这是所述的问题。
-
@CodeCaster 好的,感谢您的反馈。居高临下不是我的本意。我得到 Deserialize() 没有返回相同的对象实例。这就是为什么我说“只是检查”。