What is operator overloading in C#, and when is it appropriate?

C# OOP Intermediate 2–3 Yrs3–5 Yrs Conceptual 1 min read

Quick Answer

C# lets a type define what an operator means for it, via public static T operator +(T a, T b). It's appropriate for types that genuinely behave like values with well-known arithmetic/comparison semantics — Money, a Vector, a DateRange — where a + b reads naturally. Overriding ==/!= should be paired with overriding Equals/GetHashCode consistently.

Operator overloading lets you define what +, ==, and the rest mean for your own type, using a public static method named operator. It earns its keep on genuine value types where the operator has an obvious, unsurprising meaning — Money + Money, comparing two DateRanges for overlap. It's a bad idea when it would surprise a reader, like overloading + on something that isn't conceptually additive just because it's convenient. If I overload == I always overload != alongside it and make sure Equals and GetHashCode agree with it. These days, for a lot of these value-object cases, a record just generates the equality operators for me.

  • Good fits: math/geometry types, money, ranges, custom numeric-like value objects.
  • Bad fits: overloading + on a Logger to mean “attach a handler” — surprising to a reader, avoid cute abuse.
  • If you overload ==, also overload !=, and implement IEquatable<T> for performance in generic collections.
  • record types generate value-equality operators for you, often removing the need to hand-write them.