liveBook · Manning

Reference equality

As explained in Fabulous Adventures in Data Structures and Algorithms

Reference equality determines whether two references identify the same object rather than whether their contained values are equal.

Two objects can contain the same values without being the same object. Reference equality asks whether two references identify one object. That distinction matters when an equality operator does more work than a quick identity check: a C# record class generates value equality, so comparing two linked lists with `==` can recursively inspect their contents and may overflow the call stack on long lists. section 1.2.1

Identity becomes especially useful when construction guarantees a unique object for each value. Memoized quadtree factories deduplicate equal grids, including empty grids. With that guarantee, `this == Empty(Level)` can recognize an empty quad by comparing references rather than traversing its cells. The quick check depends on the factory invariant; reference equality alone does not establish that separately created objects have equal contents. section 4.3.5

Node equivalence without recursive edge comparisons

A directed acyclic word graph node comparer first checks `ReferenceEquals(x, y)`, then handles nulls. For distinct nodes, it compares end-of-word status, outgoing-edge counts and labels, and uses `ReferenceEquals(x.FollowEdge(e), y.FollowEdge(e))` on corresponding destinations. Thus node equivalence depends on identical destination objects, not a fresh recursive comparison of their contents. Because the comparer also supplies a hash code, mutating a stored node in a way that changes that code can make it unfindable in a hash set or dictionary. section 5.4.2

Listing 5.6 Computing Node equivalence with an equality comparer
sealed class DawgBuilder
{
    private class NodeEquality : IEqualityComparer<Node>
    {
        public bool Equals(Node? x, Node? y) 
        {
            if (ReferenceEquals(x, y))
                return true;
            if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
                return false;
            if (x.IsEnd != y.IsEnd || x.Count != y.Count)
                return false;
            return x.EdgeLabels.All(e => 
                y.HasEdge(e) && 
                ReferenceEquals(x.FollowEdge(e), y.FollowEdge(e)));
        }

The C# comparer shows the identity fast path and the reference checks on outgoing edges. section 5.4.2

The trade-off is that identity may stop answering the question you need. A deferred `Pop` on a Hughes list could be cheap, but an empty result would be hidden inside a delegate; `IsEmpty` could no longer use a reference comparison and would need to construct the resulting stack. Conversely, memoized factories for immutable unification terms could make equality comparisons fast reference checks while deduplicating symbols. Choose reference equality when the representation makes identity meaningful, not merely because it is cheap. section 2.7.6 section 10.2

How Fabulous Adventures in Data Structures and Algorithms covers it

How deep it goes
Works through C# equality pitfalls and a node comparer, but does not examine runtime reference-comparison internals.
Examples
Shows record-backed linked lists, memoized empty quadtrees, directed acyclic word graph nodes, and deferred list operations.
What it assumes
Assumes familiarity with C# records, references, and equality comparers; illustrates their different equality behavior through data structures.
What you can do after
Apply it via C# `ReferenceEquals` and memoized factories when object identity reliably answers an equality or emptiness question.
How it connects
Connects reference equality to value equality, memoization, immutable data structures, graph-node equivalence, and hash codes.

Also explained in

Compare how 4 books explain reference equality →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Fabulous Adventures in Data Structures and Algorithms. The section links point to the parts of the book it draws on.