Now that we’ve talked about the importance of implementing equality, the different kinds of equality, and about the contracts required of our implementations, we can get down to actually writing some code.

Entity Equality

When our classes represent parties, places, or things that exist outside our application, we need entity equality to ensure that we only ever have at most a single instance in memory for every item in the real world.

public class Person : IEquatable<Person>
    public Guid PersonId { get; }

    // ... elided ...

    public bool Equals(Person other)
        => other != null && PersonId.Equals(other.PersonId);
    public override bool Equals(object obj)
        => obj is Person p && Equals(p);
    public override int GetHashCode()
        => PersonId.GetHashCode();

The only thing we need compare when checking to see if two instances of Person are equal is the unique identifier, PersonId. We don’t care about any of the other properties because it’s the same person whether he calls himself Johnathon or Jon.

The C# 7 pattern matching syntax obj is Person p is very convenient here, but its use hides another subtlety: We’re not using GetType() to enforce that both classes have exactly the same type. This might seem to contradict my earlier post but it’s there for very good reason.

Many persistence frameworks, including Entity Framework and NHibernate among others, will create subclasses at runtime in order to inject functionality such as lazy loading. As a direct consequence, you might end up dealing with a PersonProxy instead of a Person - and having equality break would be bad idea.

About this series

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

Posts in this series

Why is Equality important in .NET?
Types of Equality
Equality has Symmetry
Equality and GetHashCode
Implementing Entity Equality
Implementing Value Equality
Types behaving badly
Prior post in this series:
Equality and GetHashCode
Next post in this series:
Implementing Value Equality


blog comments powered by Disqus