问题描述
我有一个 modelNoBend
类型的对象 CalculationModel
,我已将其序列化为 JSON 并使用以下内容将其保存在 .txt
文件中:
private static void GenerateTextFileNoBend(string path,CalculationModel model)
{
if (!File.Exists(path)) {
using (var file = File.CreateText(path + "noBend.txt")) {
var json = JsonConvert.SerializeObject(model);
file.Write(json);
}
}
}
然后,我想反序列化该 JSON 并检查原始对象是否相同。
static void Main(string[] args)
{
GenerateTextFileNoBend(path,modelNoBend);
var jsonText = File.ReadAllText(@"D:\5113\noBend.txt");
CalculationModel model = JsonConvert.DeserializeObject<CalculationModel>(jsonText);
string one = JsonConvert.SerializeObject(modelNoBend);
string two = JsonConvert.SerializeObject(model);
if (model.Equals(modelNoBend)) {
Console.Write("Yes");
}
if (one.Equals(two)) {
Console.Write("Yes");
}
}
if (model.Equals(modelNoBend)) - False
if (one.Equals(two)) - True
如果我比较两个对象,.Equals()
返回 false。但是,如果我再次序列化它们并比较字符串,则 if
会进入真正的分支。
显然,我在上一篇文章中遗漏了我无法编辑 CalculationModel 类。这意味着我无法遵循 this question 中的答案,因为我无法覆盖 Equals
,也无法使用其他类似 IEqualityComparer
的东西,因为它需要类来实现 IComparable
。
解决方法
好吧,既然你没有覆盖 Equals
和 GetHashCode
那么 model
和 modelNoBend
是
通过他们的引用进行比较。 model
和 modelNoBend
不共享相同的引用,即
为什么他们认为不平等。
您无法实现自定义 Equals
和 GetHashCode
,但可以实现comparer:
public class CalculationModelComparer : IEqualityComparer<CalculationModel> {
public bool Equals(CalculationModel x,CalculationModel y) {
if (ReferenceEquals(x,y))
return true;
if (null == x || null == y)
return false;
// I have nothing but serialization data to compare
//TODO: put smarter code: compare properties and fields here
return string.Equals(
JsonConvert.SerializeObject(x),JsonConvert.SerializeObject(y));
}
public int GetHashCode(CalculationModel obj) {
if (null == obj)
return 0;
// I have nothing but serialization data to compare and
// serialization is a long process... So we can put either 1 or
// JsonConvert.SerializeObject(obj).GetHashCode();
//TODO: put smarter code: compute hash from properties and fields
return 1;
}
public static IEqualityComparer<CalculationModel> Instance {get} =
new CalculationModelComparer();
}
然后使用它:
if (CalculationModelComparer.Instance.Equals(model,modelNoBend)) {
...
}
,
我希望这个答案听起来不会轻率;这不是故意的。
如果您的用例只是这个小案例,或者被检查相等性的类在字段方面相当小,那么编写一个根据需要比较字段的方法是完全合法的。
有很多情况支持这样的事情,尤其是在性能紧凑的循环中。
也就是说@Dmitry 的回答是正确的。如果有意义,我会提供它作为替代方案。