Thoughts on life, liberty, and information technology

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
{
	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.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.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!

17 responses to “Use reflection to compare the properties of two objects”

  1. Derik Whittaker Avatar
    Derik Whittaker

    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.

    Like

  2. brian Avatar
    brian

    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…

    Like

  3. TC Avatar
    TC

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

    Like

  4. Kiran Kumar Singani Avatar
    Kiran Kumar Singani

    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

    Like

  5. brian Avatar
    brian

    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.

    Like

  6. Kwame Avatar
    Kwame

    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.

    Like

  7. Swami Avatar
    Swami

    If I have a property of type List, within the “Name” class, how could I compare values? Any idea?

    Like

  8. Trevor Avatar
    Trevor

    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.

    Like

  9. Trevor Avatar
    Trevor

    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.

    Like

    1. Abhishek Agrawal Avatar
      Abhishek Agrawal

      @Trevor – can you post the correct syntax for #3.

      Like

  10. Rob Avatar
    Rob

    Trevor, good point. The code is useless.

    Like

  11. flotschie Avatar
    flotschie

    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. 🙂

    Like

  12. Rob Avatar
    Rob

    Thx. Very helpfull creating my unit tests.

    Like

  13. Greg Finzer Avatar
    Greg Finzer

    I created a class to do a deep compare of two objects on codeplex:

    http://comparenetobjects.codeplex.com/

    Like

  14. Ashish Avatar
    Ashish

    Man you are super cool…i was able crack simple object..but wot about objects inside object..?
    do you think it is going to work..?

    Like

  15. brian Avatar
    brian

    @Ashish — I would check out http://comparenetobjects.codeplex.com/ — it seems to do a lot!

    Like

  16. Jet Avatar
    Jet

    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.

    Like

Leave a comment