[英]How to maintain reference equality during serialization and deserialization
我在C#/。NET中进行序列化时遇到问题,如果在一个流中序列化对同一对象的多个引用,则在反序列化之后,这些引用将不再相等。 我正在使用默认的二进制序列化。 使我绊倒的代码是:
Check ck1 = new Check();
Check ck2 = new Check();
ck1.Numbers = new int[] { 11, 12, 13 };
ck2.Numbers = ck1.Numbers;
Console.WriteLine(ReferenceEquals(ck1.Numbers, ck2.Numbers));
FileStream fs = new FileStream("d:\\deleteme-check3.txt", FileMode.Create, FileAccess.Write);
BinaryFormatter oos = new BinaryFormatter();
oos.Serialize(fs, ck1);
oos.Serialize(fs, ck2);
fs.Flush();
fs.Close();
fs = new FileStream("d:\\deleteme-check3.txt", FileMode.Open, FileAccess.Read);
oos = new BinaryFormatter();
Check ck3 = (Check)oos.Deserialize(fs);
Check ck4 = (Check)oos.Deserialize(fs);
Console.WriteLine(ReferenceEquals(ck3.Numbers, ck4.Numbers));
声明是
[Serializable]
class Check
{
public int[] Numbers = new int[] { 0, 1, 2 };
}
当我运行此代码时,我得到True
和False
。 我正在寻找可以使用的功能,这些功能可以为True
和True
。
注意#1:我检查了周围,并看到了有关使用DataContractSerializer
和MarshalByRefObject
参考,但是我看不到如何将这些功能应用于此问题;
注意#2:我知道我可以编写自己的自定义序列化逻辑,但是我想避免这种情况,而是使用默认序列化。 例如,如果我在Java中使用默认序列化,则在这种情况下我将获得True
和True
,并且我正在.NET中寻找类似的工具。
这根本不会发生。 任何保留引用的语义仅对一次调用Serialize
/ Deserialize
。 为了得到想要的东西,您需要使用某种包装器,即
[Serializable]
public class HazTwo {
public Check First {get;set;}
public Check Second {get;set;}
}
然后序列化:
var obj = new HazTwo { First = ck1, Second = ck2 };
oos.Serialize(fs, obj);
并反序列化:
var newObj = (HazTwo)oos.Deserialize(fs);
var ck3 = newObj.First;
var ck4 = newObj.Second;
除了IObjectReference
略有例外,在IObjectReference
分别对Serailize
或Deserialize
调用之间,都不会保留引用身份,但是由于数组未实现IObjectReference
,因此这很IObjectReference
。
坦白说,我怀疑您最好选择以下两种方法之一:
Serialize
/ Deserialize
调用在起作用 我还应该添加脚注,我通常建议人们不要过度使用BinaryForamtter
我已经看到太多的人丢失数据或陷入混乱,通常是在他们的代码版本之间进行迭代时。 改变不是很容易。
编辑:不可能进行所需的比较,因为ReferenceEqual实际上是要检查它是否是同一对象。 来自msdn
与Equals方法和equals运算符不同,ReferenceEquals方法不能被覆盖。 因此,如果您要测试两个对象引用是否相等并且不确定Equals方法的实现,则可以调用ReferenceEquals方法。 但是,请注意,如果objA和objB是值类型,则在将它们传递给ReferenceEquals方法之前将它们装箱。
因此,如果您想拥有ReferenceEqual的唯一方法,就可以按照我在下面的描述进行操作。
原始帖子
在第一次检查时,由于这些陈述,您会得出正确的结论
ck1.Numbers = new int[] { 11, 12, 13 };
ck2.Numbers = ck1.Numbers;
第二行使ck2指向与ck1相同的对象。
在反序列化上
Check ck3 = (Check)oos.Deserialize(fs);
Check ck4 = (Check)oos.Deserialize(fs);
您在此处所做的是创建两个新对象,并且ck3和ck4引用了不同的对象。 为了获得与序列化之前相同的结果,请shuold执行
Check ck3 = (Check)oos.Deserialize(fs);
Check ck4 = ck3;
在这里,创建了一个新对象ck3,并且ck4 = ck3确保两者都引用同一对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.