Entities and the aggregate rootIdentity versus value
No narration yet
Module 4 · Lesson 111 min

Identity versus value

Value objects are equal by their values. Entities are equal by their identity. Two flight-note value objects with the same key and body are the same note. Two aggregates are the same aggregate only when their Id matches, even if every other field differs. That's the whole distinction: a VO is what it contains; an entity is who it is.

Fusion's Entity<TId> base makes this sharp in a way that surprises people. It doesn't just implement identity equality, it refuses value equality entirely: Equals, GetHashCode, and == all throw.

Entity forbids equality operators (domain/Entity.cs)
public override bool Equals(object? obj) =>
    throw new NotImplementedException("Don't use equality operators with entities.");

public override int GetHashCode() =>
    throw new NotImplementedException("Don't use equality operators with entities.");

public static bool operator ==(Entity<TId>? left, Entity<TId>? right) =>
    throw new NotImplementedException("Don't use equality operators with entities.");

Why be so aggressive? Because comparing two entities with == almost always means you wanted to compare their Ids and got it subtly wrong. By throwing, the base turns a silent bug into a loud one at the exact call site. When you need to know if two entity references are the same entity, compare a.Id == b.Id.

Practice

Try it yourself

Check

Confirm entity == throws

Verify the aggressive guard is real, not a story.

You should see

Reading domain/Entity.cs, every equality path — Equals(object?), Equals(Entity<TId>?), GetHashCode(), operator ==, operator != — throws NotImplementedException("Don't use equality operators with entities."). So aggregateA == aggregateB doesn't return false, it throws, which forces you to write aggregateA.Id == aggregateB.Id instead.

Recall

The two kinds of equality

One sentence each.

How is a value object equal to another, and how is an entity equal to another?

Quiz

Compare two entities

You have two FlightDisruptionAggregate references and want to know if they're the same aggregate. What do you write?