当你不能覆盖 Equals 时如何比较两个对象?

How to compare two objects when you can't override Equals?

我有一个类型为 CalculationModel 的对象 modelNoBend,我已将其序列化为 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:13\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() returns 错误。但是,如果我再次将它们序列化并比较字符串,if 会进入真正的分支。

显然,我在上次 post 中遗漏的一点是 我无法编辑 CalculationModel class。这意味着我无法遵循 中的答案,因为我无法覆盖 Equals,也无法使用其他类似 IEqualityComparer 的东西,因为它需要 class 来实现 IComparable.

是否有任何解决方法,无需我去触碰 class?

嗯,既然你不覆盖 EqualsGetHashCode那么modelmodelNoBend是 与他们的 引用 进行比较。 modelmodelNoBend 不共享相同的引用,那是 为什么他们认为不平等。 你不能实现自定义 EqualsGetHashCode 但你可以实现 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)) {
  ...
}

我希望这个回答听起来不是轻率的;这不是故意的。

如果您的用例只是这个小案例,或者要检查相等性的 class 在字段方面相当小,那么只编写一个根据需要比较字段的方法是完全合法的。

有很多案例支持这样的事情,特别是在性能的紧密循环中。

也就是说@Dmitry 的回答是正确的。当它有意义时,我会提供它作为替代方案。