How to Resolve Error "CS0216: The operator A requires a matching operator B to also be defined" in C#
The Compiler Error CS0216 is an Operator Overloading consistency error. The message reads: "The operator 'operator1' requires a matching operator 'operator2' to also be defined".
C# enforces strict rules on operator overloading to ensure logical symmetry. Certain operators are viewed as pairs. If you overload one half of the pair, the compiler requires you to overload the other half to prevent confusing or incomplete behavior. For example, if you define what "Equal" (==) means for your class, you must also define what "Not Equal" (!=) means.
This guide lists the required operator pairs and demonstrates how to implement them correctly.
Understanding Operator Pairs
The C# compiler requires the following operators to be overloaded in pairs:
trueandfalse==and!=<and><=and>=
You cannot define one without the other. This ensures that if a developer writes if (a == b), they can also logically write if (a != b).
Scenario 1: True and False Operators
As discussed in CS0215, the true and false operators allow an object to be used in conditional statements (like if (obj)). Defining only one of them triggers CS0216.
Example of error
public class Toggle
{
public bool IsOn { get; set; }
// ⛔️ Error CS0216: The operator 'true' requires a matching operator 'false'
// to also be defined.
public static bool operator true(Toggle t)
{
return t.IsOn;
}
}
Solution
Implement the matching false operator. Typically, this is the logical negation of true.
public class Toggle
{
public bool IsOn { get; set; }
// ✅ Correct: Both operators are defined
public static bool operator true(Toggle t) => t.IsOn;
public static bool operator false(Toggle t) => !t.IsOn;
}
Scenario 2: Equality and Inequality (== and !=)
This is the most common occurrence of this error. If you define custom equality logic, you must define inequality logic.
Example of error
public class User
{
public int Id { get; set; }
// ⛔️ Error CS0216: The operator '==' requires a matching operator '!='
public static bool operator ==(User a, User b)
{
// (Null checks omitted for brevity)
return a.Id == b.Id;
}
}
Solution
Define !=. Usually, you can implement it by simply negating the result of ==.
public class User
{
public int Id { get; set; }
// ✅ Correct: '==' is defined
public static bool operator ==(User a, User b)
{
if (ReferenceEquals(a, b)) return true;
if (a is null || b is null) return false;
return a.Id == b.Id;
}
// ✅ Correct: '!=' is defined as the inverse of '=='
public static bool operator !=(User a, User b)
{
return !(a == b);
}
}
When overloading == and !=, you should almost always override Equals(object o) and GetHashCode() as well to ensure consistent behavior across the .NET framework (though failing to do so generates a warning, not an error).
Scenario 3: Comparison Operators (<, >, <=, >=)
Comparison operators must also be balanced. You cannot define "Less Than" without defining "Greater Than".
Example of error
public struct Distance
{
public int Meters;
// ⛔️ Error CS0216: The operator '<' requires a matching operator '>'
public static bool operator <(Distance a, Distance b)
{
return a.Meters < b.Meters;
}
}
Solution
Implement the inverse operator.
public struct Distance
{
public int Meters;
// ✅ Correct: < matches >
public static bool operator <(Distance a, Distance b) => a.Meters < b.Meters;
public static bool operator >(Distance a, Distance b) => a.Meters > b.Meters;
// ✅ Correct: <= matches >=
// Note: If you define < and >, you usually want <= and >= as well,
// though C# treats these as separate pairs.
public static bool operator <=(Distance a, Distance b) => a.Meters <= b.Meters;
public static bool operator >=(Distance a, Distance b) => a.Meters >= b.Meters;
}
Conclusion
CS0216 guarantees logical symmetry in your custom types.
- Identify the Pair: Look at the error message to see which operator is missing.
- Implement the Inverse:
true<->false==<->!=<<->><=<->>=
- Consistency: Ensure the logic of the missing operator is the logical opposite of the existing one.