Search code examples
c#jsonserializationequality

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


I have an object modelNoBend of type CalculationModel and I have serialized it into a JSON and saved it in a .txt file using the below:

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);
      }
   }
}

Then, I wanted to deserialize that JSON and check with the original object whether they are the same or not.

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

If I compare the two objects, .Equals() returns false. However, if I serialize them both once again and compare the strings, the if goes on the true branch.

Obviously, something that I have missed out on the last post is that I can not edit the CalculationModel class. This means that I can not follow the answers in this question, since I can not override Equals, nor use something else like IEqualityComparer as it requires the class to implement IComparable.

Is there any workaround for this, without me having to touch that class?


Solution

  • Well, since you don't override Equals and GetHashCode then model and modelNoBend are compared by their references. model and modelNoBend don't share the same reference, that's why they considered being unequal. You can't implement custom Equals and GetHashCode but you can implement 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(); 
    }
    

    Then use it:

    if (CalculationModelComparer.Instance.Equals(model, modelNoBend)) {
      ...
    }