user15274463
user15274463

Reputation:

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?

Upvotes: 0

Views: 899

Answers (2)

Kit
Kit

Reputation: 21769

I hope this answer does not sound flippant; it is not meant to be.

If your use case is just this small case, or the class being checked for equality is reasonably small in terms of fields, it's totally legit to just code a method that compares the fields as needed.

There are plenty of cases that support something like this, especially in tight loops for performance.

That said @Dmitry's answer is correct. I offer this as an alternative when it makes sense.

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186843

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)) {
  ...
}

Upvotes: 2

Related Questions