Use reflection to compare the properties of two objects

In an update to WilsonORWrapper, I added a method which takes two objects of the same type and compares the properties of each, returning a value reflecting the results of the comparison. Any value other than zero would indicate that at least one property on the objects are not equal.

This method may have interest to people who don’t use WilsonORWrapper, so here’s an extracted version of the code that does the comparison.

using System;
using System.Reflection;

public static class ObjectHelper<t>
{
	public static int Compare(T x, T y)
	{
		Type type = typeof(T);
		PropertyInfo[] properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public);
		FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public);
		int compareValue = 0;

		foreach (PropertyInfo property in properties)
		{
			IComparable valx = property.GetValue(x, null) as IComparable;
			if (valx == null)
				continue;
			object valy = property.GetValue(y, null);
			compareValue = valx.CompareTo(valy);
			if (compareValue != 0)
				return compareValue;
		}
		foreach (FieldInfo field in fields)
		{
			IComparable valx = field.GetValue(x) as IComparable;
			if (valx == null)
				continue;
			object valy = field.GetValue(y);
			compareValue = valx.CompareTo(valy);
			if (compareValue != 0)
				return compareValue;
		}

		return compareValue;
	}
}

With that, if you had a Name class in your code that had two properties, First and Last, you could do something like this:

Name n1 = new Name();
n1.First = "Brian";
n1.Last = "DeMarzo";

Name n2 = new Name();
n2.First = "Brian";
n2.Last = "DeMarzo";

int result1 = ObjectHelper<name>.Compare(n1, n2);
// result1 == 0 because n1 and n2 have equal properties

n1.First = "Alyssa";
// change the first name, so n1 should no longer equal n2

int result2 = ObjectHelper</name><name>.Compare(n1, n2);
// result2 != 0 because n1 and n2 do not have equal properties

Code like this came in handy in my project where I use FileHelpers (see my blog entry from earlier today), where I was able to compare a class loaded from the database (using an O/R mapper) with a class loaded from a text file (using FileHelpers). Since the O/R mapper and FileHelpers used the same class, using this comparison method to determine if the objects were “equal” let me determine whether or not the data loaded from the database was different from the data in the text file.

Even though it used reflection, there wasn’t a huge performance hit, either. Sure beats writing manual comparison methods, which could take a while when you have a few dozen classes!

0 thoughts on “Use reflection to compare the properties of two objects

  • I like your solution. I have actually thought about writing the same type of thing before, but I’m too lazy.

    You could just serialize out the objects to XML strings them do a simple compare on the strings. This does make the assumption the objects are marked as serializable.

  • Interesting idea with the XML serialization. It’s easy enough to tell if an object is serializable (i.e. examine attributes). I wonder which approach would perform better? The advantage of XML serialization is that we’re only comparing one value, though the serialization itself has overhead. Something to experiment with…

  • Thank you – very useful code. I intend to use similar code for unit testing when comparing expected and actual results for complex objects.

  • Kiran Kumar Singani says:

    Hi ,
    You have done great job, but one thing i found in your code is , there is not handling for internal objects which are not
    t derived from the IComparable. Missing functionality for collection objects.
    Regards,
    Kiran Kumar Singani

  • The code isn’t really intended to compare everything (such as collection comparison, which could be very cumbersome). Perhaps a more “generic” way would be to get each property value’s hash code and compare those — that would, at least, eliminate the IComparable requirement, though it wouldn’t be as precise.

  • Great article! We are facing a similar task which involves implementing an audit trail that requires us to to record what data was changed. Like Brain mentioned we considered serializing the objects and looking for changes but I think a direct object comparison is definitely more elegant. Thanks for sharing.

  • It is obvious that nobody has actually tried your code.

    1) You have a lower case T in the ObjectHelper declaration (won’t compile)
    2) You are setting n2.Last before you instantiated the class (the first/last properties are mixed up).
    3) You wrote ObjectHelper.Compare(n1, n2) and its a generic type… it needs to be: ObjectHelper.Compare(n1, n2).

    4) It would be a lot more helpful if you demonstrated a base class that used such a technique such that every object that inherits from the class will automatically compare and equate by using all properties. Of course more than just Equals needs to be overridden, the operators too.
    5) I am not sure why you are comparing fields, does it make sense to have classes that are not equal based on non-public field values? Anyone interacting with the object would be confused.

  • I see this message box strips out the bracket characters…. perhaps that is what happened on step #3 which makes my post make no sense for line 3.

  • Hi, I also think about using your code for tracking changes in business objects.
    It would be great if the return value is not only a integer, but provides the information which property(ies) (string name) is(are) different and the two different values of each property in a way that you have the complete information where the two objects differ from each other. 🙂

  • As part of the refactoring I was doing to the load code for crawler projects I needed a way of verifying that new code was loading data correctly. As it would be extremely time consuming to manually compare the objects, I used Reflection to compare the different objects and their properties. This article briefly describes the process and provides a complete helper function you can use in your own projects.

Leave a Reply to JDub Cancel Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.