This handy little package does one simple thing, and it does it well. According to its description, DeepEqual is:

An extensible deep comparison library for .NET.

I am sure you too have come across this a few times. You have some code that shuffles around objects, and at some point, you’d like to make sure that two instances of the same class are, indeed, equal. And no, you don’t mean “equal” as in reference equality. That’s easy to achieve with .NET. Most of the time, what you want is to check for value equality.

Now, when it comes to value equality, there are a few things you can do in .NET: override Object.Equals() (which, by the way, if the type is a reference type, by default will check for reference equality), implement the IEquatable interface, override the == operator or, most commonly, a combination of these techniques.

The problem with this is, it can get messy real quick, especially if you are checking instances of non-sealed classes. Quoting the documentation’s Note for Callers:

When you call the Equals method to test for equality, you should know whether the current instance overrides Object. Equals and understand how a particular call to an Equals method is resolved. Otherwise, you may be performing a test for equality that is different from what you intended, and the method may return an unexpected value (source).

Sometimes you don’t know the inner details about the classes you are playing with. Also, at least in my case, many times I am performing these checks in my tests, not in the application itself. Implementing all this comparison logic just for the sake of testing would be, in my opinion, overkill.

Sometimes (most of the times?), you only need to make sure two instances are equal by value, and very deeply at that. DeepEqual comes in handy:

bool result = object1.IsDeepEqual(object2);

Simple as that. Again, I find this package invaluable especially when doing tests. Actually, I suspect I am only using it in my test. When used inside a test, you can call ShouldDeepEqual:

object1.ShouldDeepEqual(object2);

This method throws an exception with a detailed description of the differences between the two objects. You can pass a custom comparison as the second argument to the ShouldDeepEqual method, to override the default behavior. You can also customize the behavior inline, using the WithDeepEqual extension method:

object1.WithDeepEqual(object2)
   .SkipDefault<MyEntity>()
   .IgnoreSourceProperty(x => x.Id)
   .Assert()

I have been using this package for a long time. At some point, I even submitted a pull request to port it to NetStandard. Despite a lot of people loving it, the pull request was left there unnoticed for quite some time. I was asked to release a fork, I declined (somebody else did). In the end, the package author came back from the void to release a new, NetStandard compatible, update, which is fantastic. Sometimes in open source, it takes a little patience.

Enjoy.

Join the newsletter to get an email alert when a new post surfaces on this site. If you want to get in touch, I am @nicolaiarocci on twitter.