【发布时间】:2016-05-13 20:20:59
【问题描述】:
我在 C# 中使用复制构造函数实现了深度克隆方法。为了验证它是否有效,我通过比较序列化对象和它的克隆的结果来测试它。序列化是根据通用对象 T 完成的。我也根据具体对象进行了尝试,得到了相同的结果。
我有一种将对象序列化为字节数组的方法
private byte[] ObjectToBytes(T obj)
{
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
formatter.Serialize(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}
}
以下代码可以正常工作。
T original = this.GetNewThing();
T clone = original.DeepClone();
// serialize after cloning
byte[] originalBytes = ObjectToBytes(original);
byte[] cloneBytes = ObjectToBytes(clone);
bool equal = true;
for (int i = 0; i < originalBytes.Length; i++)
{
if(originalBytes[i] != cloneBytes[i]
{
equal = false;
break;
}
}
equal == true; // True!
但是,当我切换对象序列化的顺序时,字节数组不再相等。
// serialize before cloning
T original = this.GetNewThing();
byte[] originalBytes = ObjectToBytes(original);
T clone = original.DeepClone();
byte[] cloneBytes = ObjectToBytes(clone);
bool equal = true;
for (int i = 0; i < originalBytes.Length; i++)
{
if(originalBytes[i] != cloneBytes[i]
{
equal = false;
break;
}
}
equal == true; // False!
为什么序列化的顺序会影响这个?它与 BinaryFormatter 或 MemoryStream 对象有关吗?
编辑:
这是深度克隆方法的样子
public MyClass DeepClone()
{
return new MyClass(this);
}
它使用的构造函数看起来像这样
protected MyClass(MyClass myClass)
{
if (myClass == null)
throw new ArguementNullException("myclass");
this.number = myClass.Number;
this.number2 = myClass.Number2;
this.number3 = myClass.Number3;
}
对象绝不是复杂的。所有被复制的值都是值类型,所以没有需要担心的引用类型。
【问题讨论】:
-
请发布 DeepClone 方法.. 可能有问题
-
可能与对象的复杂性有关 - 看看这个:stackoverflow.com/questions/5017274/…
-
认为我们可能还需要查看完整的
MyClass。此外,它没有状态,那么为什么ObjectToBytes是私有实例方法,而不是静态的?我认为,如果您可以格式化一个完整的示例代码,可以将其剪切/粘贴到例如 LinqPad 上,这可能会有所帮助。 -
我刚刚在 LinqPad 中运行了这个,缺少的细节用我刚刚编写的最小示例填充。两种情况下的字节数组都是相等的。问题出在您未显示的某处,可能在类本身中,也可能是在
MyClass(MyClass myClass)构造函数中调用的属性访问器中的逻辑。 -
检查所有这些属性 - 可能是读取属性会改变状态。
标签: c# .net serialization