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.
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
beta, each containing the same items:
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 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:
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.
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:
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.