Having established the importance of equality in .NET, we can look at the different kinds of equality that you might encounter. There are three - Reference, Value and Entity equality.

Reference Equality

This is the default implementation of equality, inherited from object and used by any class that doesn’t explicitly override it with a new implementation.

In many ways, the most restrictive form, this kind of equality says that two object references are equal if and only if they are referring to the exact same object, even if they might look exactly the same.

For example, what if you have two lists alpha and beta, each containing the same items:

var alpha = new List<int> { 1, 2, 3 };
var beta = new List<int> { 1, 2, 3 };

I hope it’s pretty obvious that these are different lists. Adding a new item to alpha shouldn’t also change beta - the lists are independent.

Reference equality is appropriate when the two things being compared have independent lifecycles or functionality that means one cannot be substituted for another. Most mutable container classes fall into this category.

Value Equality

Value equality is useful when the information contained by the class completely defines the item.

For example, what if you have two independent representations of the same point:

var alpha = new Point( 3, 4 );
var beta = new Point( 3, 4 );

As both of these variables reference exactly the same location (coordinate) on a number plain, they’re equal. You could use either one in place of the other and the behaviour of your program would be unchanged.

Value equality is appropriate when the instance is completely defined by the values contained by the class. Immutable objects are typically treated as value types.

Entity Equality

When your classes represent something that exists outside of your application, you might find entity equality to be appropriate.

For example, if you’ve loaded details about the same person into memory twice, both instances represent the same person:

var alpha = Person.LoadById(42);
var beta = Person.LoadById(42);

Many persistence tools, including the object-relational mappers commonly used for working with SQL databases, rely on each object correctly implementing entity equality in order to ensure loaded entities are unique in memory.

About this series

Why does the implementation of Equality matter in .NET and how do you do it right?

Posts in this series

1 Why is Equality important in .NET?
2 Types of Equality
3 Equality has Symmetry
4 Equality and GetHashCode


blog comments powered by Disqus