TheDocumentation Index
Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
Use this file to discover all available pages before exploring further.
== (equality) operator is a binary comparison operator that evaluates whether its two operands are equal, returning a bool value. Its underlying evaluation mechanism depends strictly on the type of the operands being compared: built-in primitives evaluate for numeric or boolean equality, while reference types default to evaluating for reference equality (identity), unless the operator is explicitly overloaded.
Evaluation Mechanics by Type
Value Types (struct, enum, primitives)
For built-in primitive value types (e.g., int, bool, char), the operator evaluates numeric or boolean equality using direct Intermediate Language (IL) instructions. For enum types, the operator compares the underlying integral values. For user-defined struct types, the == operator is not available by default and will result in a compiler error unless explicitly overloaded.
Reference Types (class, object)
For standard reference types, the operator evaluates reference equality. It returns true only if both operands point to the exact same memory address on the managed heap. It does not inspect the data contained within the objects.
Strings (string)
Although string is a reference type, the .NET framework overloads the == operator to perform an ordinal, case-sensitive value comparison of the underlying character sequences. The implementation explicitly performs a reference equality check (object.ReferenceEquals) as an initial fast-path optimization before falling back to a character-by-character comparison.
Delegates (delegate)
Delegate types (derived from System.MulticastDelegate) overload the == operator to perform value-based equality on their invocation lists. Two distinct delegate instances will evaluate to true if they point to the exact same target instances and method pointers in the same order.
Record Types (record class, record struct)
For both reference-based records (record or record class) and value-based records (record struct, introduced in C# 10), the compiler automatically synthesizes an overloaded == operator. This generated operator performs value-based equality by executing a member-wise comparison of all properties and fields.
Tuple Types (ValueTuple)
Since C# 7.3, tuple types have built-in support for the == operator. The compiler evaluates tuple equality by performing a short-circuiting, element-wise comparison of the corresponding tuple elements in their declared order.
Nullable Value Types (Nullable<T>)
For nullable value types, the compiler provides “lifted” operators. If both operands are null, == evaluates to true. If one operand is null and the other has a value, it evaluates to false. If both operands possess values, the operator unwraps them and applies the underlying type T’s == operator.
Floating-Point Types (float, double)
Floating-point equality adheres to IEEE 754 standards. Consequently, comparing NaN (Not a Number) yields false even when compared against itself (Double.NaN == Double.NaN evaluates to false).
Generics
Comparing two instances of an unconstrained generic type parameter (t1 == t2) results in a compiler error (CS0019). The compiler cannot guarantee that the unknown type substituted for T will support the == operator. However, comparing an unconstrained generic operand to null (e.g., t1 == null) is perfectly valid C# and compiles successfully. The compiler handles the null check dynamically based on whether T resolves to a reference type or a value type at runtime.
To use == to compare two generic instances to each other, the type parameter must be constrained:
- Reference Type Constraint: Constraining
Ttoclass(where T : class) instructs the compiler to emit a reference equality check. - Base Class Constraint: Constraining
Tto a specific base class that overloads the==operator instructs the compiler to emit a call to that specific overloaded operator. - Static Abstract Interface Constraint (C# 11+):
Tcan be constrained to an interface with static abstract operators, such aswhere T : IEqualityOperators<T, T, bool>. This allows the==operator to be resolved generically for any conforming type, including value types.
Operator Overloading
The== operator can be redefined for user-defined types using the operator keyword. C# enforces a strict pairing rule: if a type overloads the == operator, it must also overload the != (inequality) operator.
When overloading ==, developers must also override the virtual Object.Equals(object) method and Object.GetHashCode() to prevent compiler warnings (CS0660 and CS0661) and ensure logical consistency across the .NET ecosystem (e.g., when the type is used as a key in a hash-based collection).
Intermediate Language (IL) Representation
At the compiler level, the behavior of== dictates the emitted Common Intermediate Language (CIL):
- For built-in primitives and reference identity checks, the compiler emits the
ceq(compare equal) opcode. - For types with an overloaded
==operator, the compiler emits acallinstruction invoking the static methodop_Equality(Type, Type)generated by the compiler for that specific type.
Master C# with Deep Grasping Methodology!Learn More





