How do I check for nulls in an '' operator overload without infinite recursion?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When overloading == in C#, the easiest mistake is using == null inside the operator itself. That triggers the overloaded operator again, which calls itself again, and you end up with infinite recursion.
The safe pattern is to bypass the overloaded operator for null checks, usually with ReferenceEquals, and keep ==, !=, Equals, and GetHashCode aligned around one consistent equality definition.
Why Recursion Happens
This implementation looks innocent but is broken:
The problem is that left == null calls the overloaded == operator again. That new call runs the same code, which performs the same check, and so on forever.
Use ReferenceEquals for Null Checks
ReferenceEquals checks object identity directly and does not route back through your overloaded operator:
This handles all of the important cases safely:
- both values are
null - one is
null - both references point to the same object
- two different instances compare equal by value
Put the Real Equality Logic in Equals
The == operator should not invent a second equality system. A good design is:
- implement
IEquatable<T> - implement
Equals(object?) - implement
GetHashCode() - let
==and!=delegate to that logic
That keeps equality behavior consistent across operators, dictionaries, sets, and APIs that call Equals rather than ==.
If == says two values are equal but Equals disagrees, the type becomes very hard to reason about.
Prefer Modern Language Features When Possible
If the type is a straightforward value object, records can save you from writing most of this code by hand:
Manual operator overloads make sense only when you need custom semantics beyond what records or built-in value semantics already provide.
Test the Edge Cases Directly
Equality bugs hide at the edges, so test those edges explicitly:
If your implementation is recursive or inconsistent, these cases usually expose it quickly.
Common Pitfalls
The biggest mistake is using == null or != null inside the overloaded operator itself. Those expressions call the operator again and create recursion.
Another common issue is overloading == without overriding Equals and GetHashCode. That leads to surprising behavior in collections and APIs that use object equality rules.
Developers also forget the identity shortcut. If both references point to the same object, you can return true immediately before doing any value comparison.
Finally, do not write manual equality code if a record or simpler type design already matches the use case. Less custom equality logic usually means fewer bugs.
Summary
- Do not use
== nullinside an overloaded==operator. - Use
ReferenceEqualsto perform null and identity checks safely. - Keep
==,!=,Equals, andGetHashCodeconsistent with one equality definition. - Implement
IEquatable<T>for strongly typed equality logic. - Prefer records or simpler built-in semantics when custom operator logic is unnecessary.

