What is the difference between == and .Equals() in C#?
Learn the difference between == and .Equals() in C#, covering reference vs value equality, null-safety, overriding rules and code examples for interviews.
Expected Interview Answer
In C#, == is an operator resolved at compile time whose meaning can be overloaded per type, while .Equals() is a virtual method resolved at runtime through polymorphism. For value types both compare values, but for reference types == defaults to reference equality unless overloaded, whereas .Equals() can be overridden to compare content.
Because == binds statically, the comparison used depends on the compile-time type of the operands, not the actual runtime object. .Equals(), being virtual on System.Object, dispatches to the most-derived override based on the real object. A key practical difference is null: obj.Equals(x) throws if obj is null, but == handles null safely. String is a common case where both compare by value, but comparing boxed values or objects declared as object can give surprising results with ==.
- .Equals() supports polymorphic, runtime value comparison via overrides
- == can be overloaded to give intuitive value semantics per type
- == is null-safe on both sides, unlike calling .Equals() on a possibly-null reference
- Object.Equals(a, b) static helper avoids null-reference exceptions
- Understanding both prevents subtle bugs when comparing objects typed as object
AI Mentor Explanation
Comparing two players with == is like checking if two names on the team sheet point to the exact same registered person, decided the moment the sheet is printed. .Equals() is like the umpire comparing them live on the field by an agreed rule such as identical stats, judging the actual players in front of him rather than the printed labels.
Step-by-Step Explanation
Step 1
Recognize == is an operator
== is resolved at compile time based on the static type and can be overloaded per type.
Step 2
Recognize .Equals() is a method
.Equals() is virtual on System.Object and dispatches at runtime to the most-derived override.
Step 3
Check value vs reference types
Value types compare by value for both; reference types default == to reference equality unless overloaded.
Step 4
Handle null safely
Use == or Object.Equals(a, b) to avoid the NullReferenceException that obj.Equals(x) throws when obj is null.
Step 5
Override consistently
When overriding Equals, also override GetHashCode and consider overloading == to keep behavior consistent.
What Interviewer Expects
- == is compile-time/overloadable, .Equals() is runtime/virtual
- Reference vs value equality defaults for each
- Null-safety difference between == and instance .Equals()
- Knowing string compares by value with both
- The rule that overriding Equals means overriding GetHashCode
Common Mistakes
- Assuming == always compares values for reference types
- Calling .Equals() on a reference that may be null
- Overriding Equals but forgetting to override GetHashCode
- Expecting == on objects typed as object to compare content
- Confusing reference equality with structural/value equality
Best Answer (HR Friendly)
“In C#, == is an operator that checks equality and can be customized per type, while .Equals() is a method that compares objects and can be tailored by inheritance. For simple values they usually behave the same, but for objects == often checks if they are the exact same instance while .Equals() can be set up to compare their contents.”
Code Example
object a = 1000;
object b = 1000;
// == on objects compares references (boxes) -> false
bool byOperator = (a == b); // False
// Equals is overridden by Int32 to compare values -> true
bool byMethod = a.Equals(b); // True
string s1 = "hi";
string s2 = "h" + "i";
Console.WriteLine(s1 == s2); // True - string overloads ==
Console.WriteLine(s1.Equals(s2)); // True - value comparison
// Null-safe comparison:
string n = null;
Console.WriteLine(n == "x"); // False, no exception
// n.Equals("x") would throw NullReferenceExceptionFollow-up Questions
- Why should you override GetHashCode whenever you override Equals?
- How does ReferenceEquals differ from == and .Equals()?
- What happens with == when comparing two boxed value types?
- How do records change equality behavior in modern C#?
- When does string interning make == return true unexpectedly?
MCQ Practice
1. How is the == operator resolved in C#?
== is a static operator resolved at compile time using the operands' compile-time types, and it can be overloaded per type.
2. Which comparison can throw a NullReferenceException?
Calling the instance method a.Equals(b) throws if a is null; == and the static Object.Equals are null-safe.
3. For two objects typed as object holding equal ints, a == b returns?
As object, == compares references to the two separately boxed values, which are different, so it returns False.
Flash Cards
Is == a method or operator? — An operator, resolved at compile time and overloadable per type.
Is .Equals() static or dynamic dispatch? — Virtual on System.Object, so it dispatches at runtime to the actual type's override.
Which is null-safe? — == (and Object.Equals(a,b)) are null-safe; a.Equals(b) throws if a is null.
Override Equals means also override? — GetHashCode, to keep hash-based collections consistent.