110

what is the best way to compare two objects and find the differences?

Customer a = new Customer();
Customer b = new Customer();
Nick Kahn
  • 19,652
  • 91
  • 275
  • 406

2 Answers2

249

One Flexible solution: You could use reflection to enumerate through all of the properties and determine which are and are not equal, then return some list of properties and both differing values.

Here's an example of some code that is a good start for what you are asking. It only looks at Field values right now, but you could add any number of other components for it to check through reflection. It's implemented using an extension method so all of your objects could use it.

TO USE

    SomeCustomClass a = new SomeCustomClass();
    SomeCustomClass b = new SomeCustomClass();
    a.x = 100;
    List<Variance> rt = a.DetailedCompare(b);

My sample class to compare against

    class SomeCustomClass
    {
        public int x = 12;
        public int y = 13;
    }

AND THE MEAT AND POTATOES

using System.Collections.Generic;
using System.Reflection;

static class extentions
{
    public static List<Variance> DetailedCompare<T>(this T val1, T val2)
    {
        List<Variance> variances = new List<Variance>();
        FieldInfo[] fi = val1.GetType().GetFields();
        foreach (FieldInfo f in fi)
        {
            Variance v = new Variance();
            v.Prop = f.Name;
            v.valA = f.GetValue(val1);
            v.valB = f.GetValue(val2);
            if (!Equals(v.valA, v.valB))
                variances.Add(v);

        }
        return variances;
    }


}
class Variance
{
    public string Prop { get; set; }
    public object valA { get; set; }
    public object valB { get; set; }
}
Bigbob556677
  • 1,805
  • 1
  • 13
  • 38
deepee1
  • 12,878
  • 4
  • 30
  • 43
  • 36
    Use if (!Equals(v.valA, v.valB)) in place of if (!v.valA.Equals(v.valB)) to prevents NullException – Jerome2606 Mar 03 '15 at 08:16
  • Why not auto properties ? – Thomas Ayoub Mar 24 '15 at 09:08
  • 7
    If .GetFields() does not return everything you want (like private fields), check out this post: http://stackoverflow.com/questions/1040803/whats-wrong-with-this-reflection-code-getfields-is-returning-an-empty-array – Kjensen Jun 09 '15 at 12:46
  • 8
    5 years later and this was totally what I was looking for. I just had to switch to GetProperties and it worked like a charm (for my needs) – Francisc0 Oct 07 '16 at 19:11
  • 10
    I like this idea, but the code here doesn't work. Here's a fiddle that shows a couple of fixes: https://dotnetfiddle.net/FhzcrS – Don Rolling Aug 23 '17 at 18:51
  • Was answered 8 years ago, but still relevant. Btw, if the property of type `Dictionary` how to compare it properly in a most efficient way? –  Apr 15 '19 at 20:20
  • To skip navigation properties in object added conditions to skip iteration when `property.PropertyType is IEnumerable` or `property.PropertyType.IsClass && property.PropertyType != typeof(string)` – Daniel Žeimo May 10 '19 at 12:25
  • outputs a bund of .net language names when the class is a child class, can this be modified to compare child classes too? – Smith Mar 26 '21 at 19:36
  • Not to be pendantic, but it _will_ show up in Visual studio code - why are properties `valA` and `valB` not capitalized? I suppose with conventional naming practice they should be. – fullStackChris Jun 22 '22 at 16:41
14

The Equals method and the IEquatable<T> interface could be used to know if two objects are equal but they won't allow you to know the differences between the objects. You could use reflection by comparing each property values.

Yet another approach might consist into serializing those instances into some text format and compare the differences inside the resulting strings (XML, JSON, ...).

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 3
    I think he's not looking for equality tests, but rather the collection of reasons why the two objects do not match. – deepee1 Feb 09 '11 at 22:28
  • Sure, but that doesn't really make sense seeing as we have no idea what's contained in the Customer class – Rob Feb 09 '11 at 22:29
  • 1
    @deepee1, @Rob, I agree that `Equals` and `IEquatable` doesn't allow for finding the differences. Reflection could be used in this case. – Darin Dimitrov Feb 09 '11 at 22:31