TDD, reflection and the PropertiesEqual extension method

In my last post I wrote about the extension method ForEach, which is a very simple but useful method, at least when it comes to readability.

In this post I’ll try to explain another extension method, which I’ll call PropertiesEqual. It’s purpose is to extend the object class with a method to compare the properties of two objects:

public static bool PropertiesEqual<T>(this T obj1, T obj2)
return true if all properties of obj1 equals all properties of obj2

You probably know of the object.Equals method, which per default compares the memory addresses of two objects. That is, two objects are equal only if they are exactly the same object. If you really want to compare the content of two objects, you need to override this function in your class and manually compare them.

When I designed this function, I started with two simple test cases:
1. If two objects of the same class have the same public properties, yield true
2. If two objects of the same class have different public properties, yield false

Translated to code, this becomes:

class TestClass
public int A { get; set; }
public int B { get; set; }
public void PropertiesEqualTest()
Assert.IsTrue(new Test { A = 1, B = 1 }.PropertiesEqual(new Test { A = 1, B = 1 }));
Assert.IsFalse(new Test { A = 1, B = 1 }.PropertiesEqual(new Test { A = 1, B = 0 }));

The implementation is very straight forward:

public static bool PropertiesEqual<T>(this T obj1, T obj2)
return typeof(T).GetProperties().All(property =>
var prop1 = property.GetValue(obj1, null);
var prop2 = property.GetValue(obj2, null);
return prop1.EqualsTo(prop2);

typeof(T).GetProperties() will return all public properties of T, and property.GetValue(obj, null) will return the value of a given property. The All extension method returns true only if all elements of the sequence satisfy the given condition, i.e. all properties are equal.

The test cases will pass fine, and we now have a simple way of comparing properties of two objects! In the next post I’ll try to describe how to extend the method with support for recursive properties (compare properties of a property), and in the one after that I’ll write about how to implement an IEqualityComparer based on this method.

EDIT: Note, these series aren’t much of the type “here is a revolutionary new technique”, but more of “here is how I would write the code for this”. My focus is to get you to understand how I think when I design methods, not to tell you that “this is the way”!

About gustafnk

Developer at Jayway, REST/Hypermedia, AWD, Software apprentice, Dvorak user, Christian atheist, Zizek fan. I'm on twitter: @gustaf_nk
This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to TDD, reflection and the PropertiesEqual extension method

  1. peteter says:

    I haven't look in the docs for property.GetValue, but wouldn't you want to use 'default' of the type for the property instead?

  2. Hm, not sure what you mean, but the docs says the following:Returns the value of the property with optional index values for indexed properties.The second parameter is thus the index value, which should be null for non indexed properties.

  3. peteter says:

    Ok Genne, never mind my comment.But shouldn't I get a little creds for bringing up the idea of writing an equal method as extension methods, when we had sushi last?

  4. Didn't remember I had the idea from then, just thought that "writing a property equality extension method would be cool!". If I got the idea from you, which doesn't sound unlikely, then creds to you!Why don't you write your own implementation so that we can compare each others?

  5. peteter says:

    Well actually we discussed extension methods in general, and I was looking for an example of them. I said an equal method, and has some, vague, ideas why it would be a good idea (forgot now 🙂 But you argued against it pretty strong, and I was a bit surprised when you wrote an extension method for the object class that compared objects (although for properties).So anyhow … 🙂

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s