1

I have two complex objects of the same type. I want to check if there is any difference between the two of these objects. I have two options of achieving this, either by converting both of these objects to string using JsonConvert.SerializeObject and compare the string like

var existingData = JsonConvert.SerializeObject(objOld);
var newData = JsonConvert.SerializeObject(objNew);
return existingData == newData;

The other option is to use the reflection and loop through all the properties like below.

    protected bool MatchObject(object newObj, object oldObj)
    {
        Type currentType = newObj.GetType();
        PropertyInfo[] props = currentType.GetProperties();

        bool isSameObject = true;
        foreach (var prop in props)
        {
            var i = prop.GetValue(newObj);
            var f = prop.GetValue(oldObj);
            if (!object.Equals(i, f))
            {
                isSameObject = false;
                break;
            }
        }

        return isSameObject;
    }

Which of the above approach is more efficient as per the performance perspective?

Rahul Kumar
  • 11
  • 1
  • 2
  • 1
    have a look at [best-way-to-compare-two-complex-objects](https://stackoverflow.com/questions/10454519/best-way-to-compare-two-complex-objects) – Mong Zhu Nov 23 '21 at 06:30
  • If you have control of the object source, you can define a hashing function by overriding `getHashCode` based on all the properties (or the serialized version of the class instance), and then compare the hashes, either directly or by overriding `.Equals` or `==` operators (preferably the former). – mcy Nov 23 '21 at 06:31
  • It is officially discouraged by Microsoft themselves to override `GetHashCode` for mutable reference types, [here](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=net-6.0#notes-to-inheritors) (see the 2 bullet points for exceptions) – MindSwipe Nov 23 '21 at 06:47
  • True, If you are going to store these objects in a hash table, then you should not modify the mutable properties while the object is still in the hash table. If you are just going to compare two instances, it might not cause issues. – mcy Nov 23 '21 at 06:58
  • 1
    The key words there for me are "while it is contained in" - if it can exist outside of a dictionary for those times it is mutated, or if you will only ever load it into a dictionary and do some non mutating thing with it, I don't have a problem with it. Sometimes "don't do silly thing x" is allowed to be in the hands of the developer not doing that thing, rather than needing code to make sure developers can't do that thing ;) – Caius Jard Nov 23 '21 at 07:09
  • How about writing an `IEqualityComparer`? – Oliver Nov 23 '21 at 08:40
  • Hope this question can answer your query. [Get list of matching objects from 3 different lists](https://stackoverflow.com/questions/72444334/get-list-of-matching-objects-from-3-different-lists) – Aԃιƚყα Gυɾαʋ Jun 01 '22 at 09:40

2 Answers2

8

Ugh. Faced between "serialize it to string and use string compare" and "use reflection" I think I'd tick the "none of the above" box

Have you considered using a record instead of a class? The compiler writes all the necessary code for you, to determine equality of a record based on the values of its properties, so all that is left for you to do is test your record instances for equality

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Aside being a C# 9.0 feature, I think this looks like the best approach. It feels like Kotlin data classes, takes a lot of boilerplate code off the hands of the developer. – mcy Nov 23 '21 at 11:06
1

Alternative ready-to-use option is assertion frameworks. For example 'FluentAssertions' can compare object graph

newObject.Should().BeEquivalentTo(oldObject);

Line above will throw an exception if object and their properties aren't equal.
Object graph comparison

Notice that this is just another library available via NuGet, so you can use in the "production" code as well ;)

Fabio
  • 31,528
  • 4
  • 33
  • 72