← Back to Articles         
Difference between ==, Equals(), and ReferenceEquals()

Difference between ==, Equals(), and ReferenceEquals()

Published on 12 Oct 2026     10 min read C#
C# Fundamentals
 

C# Object Comparison – Difference Between ==, Equals(), and ReferenceEquals()

In C#, ==, Equals(), and ReferenceEquals() are used to compare values or objects.

However, they differ in how comparisons are performed, whether they compare values or object references, and whether their behavior can be customized.

1. What is the == operator in C#?

The == operator is used to compare two operands for equality.

Its behavior depends on the data type and whether the operator has been overloaded.

  • For built-in numeric types, it compares values.

  • For most classes without a custom == operator, it compares object references.

  • For strings, it compares text content.

Example 1: Value type comparison

int a = 10;
int b = 10;

Console.WriteLine(a == b); // True

Explanation:

  1. a contains the value 10.

  2. b contains the value 10.

  3. The == operator compares their values.

  4. Both values are equal, so it returns true.

Example 2: Reference type comparison

public class Employee
{
    public int Id { get; set; }
}

Usage:

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

Console.WriteLine(emp1 == emp2); // False

Why does it return false?

Although both objects contain the same Id, they are two different objects in memory.

The Employee class does not overload the == operator, so reference equality is used.

Memory representation

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

       emp1                  emp2
         |                     |
         v                     v
  +---------------+     +---------------+
  | Employee      |     | Employee      |
  | Id = 101      |     | Id = 101      |
  +---------------+     +---------------+
       Object 1              Object 2

emp1 == emp2

Result: False

Reason:
Both variables reference different objects.

Example 3: String comparison

string a = new string("Hello".ToCharArray());
string b = new string("Hello".ToCharArray());

Console.WriteLine(a == b); // True

Why does it return true?

The string class overloads == to compare string content rather than object identity.

Even though a and b are separate string objects, their contents are equal.

Key Points

  • Operator: == is an equality operator.

  • Value Types: Built-in numeric types are compared by value.

  • Reference Types: Classes without overloaded equality generally use reference comparison.

  • Strings: Compare content because string overloads ==.

  • Customization: Classes and structs can overload ==.

  • Null: Can be used to check for null where the operator is applicable, although overloaded operators can have custom behavior.

  • Common Usage: Comparing numbers, strings, and objects with defined equality operators.

 

2. What is the Equals() method in C#?

The Equals() method is used to determine whether two values or objects are equal.

It is defined in System.Object and can be overridden by derived classes to provide custom value-based comparison.

Example 1: Value type comparison

int a = 10;
int b = 10;

Console.WriteLine(a.Equals(b)); // True

Explanation:

  1. a contains 10.

  2. b contains 10.

  3. Equals() compares the integer values.

  4. Both are equal, so it returns true.

Example 2: Reference type comparison

public class Employee
{
    public int Id { get; set; }
}

Usage:

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

Console.WriteLine(emp1.Equals(emp2)); // False

Why does it return false?

By default, a normal class inherits Object.Equals(), which uses reference equality.

Even though both objects contain the same data, they are different instances.

Example 3: Overriding Equals()

We can override Equals() to compare objects based on their properties.

public class Employee
{
    public int Id { get; set; }

    public override bool Equals(object? obj)
    {
        if (obj is Employee other)
        {
            return Id == other.Id;
        }

        return false;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Usage:

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

Console.WriteLine(emp1.Equals(emp2)); // True
Console.WriteLine(emp1 == emp2);      // False

Explanation:

  1. emp1 and emp2 are different objects.

  2. We override Equals() to compare the Id property.

  3. Both objects have Id = 101.

  4. Therefore, Equals() returns true.

  5. == still returns false because we have not overloaded that operator.

Important: When overriding Equals(), also override GetHashCode() consistently. Objects considered equal must produce the same hash code.

How Equals() works

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

        emp1                  emp2
          |                     |
          v                     v
   +---------------+     +---------------+
   | Id = 101      |     | Id = 101      |
   +---------------+     +---------------+
          |                     |
          +----------+----------+
                     |
                     v
              Equals(emp2)
                     |
                     v
             Compare Id values
                     |
                     v
                101 == 101
                     |
                     v
                    True

What is the difference between instance Equals() and object.Equals()?

Instance method:

string? name = null;

// name.Equals("John"); // NullReferenceException

Static method:

string? name = null;

Console.WriteLine(object.Equals(name, null)); // True

The static object.Equals(a, b) method safely handles null references.

Key Points

  • Method: Equals() is defined in System.Object.

  • Default Behavior: For ordinary classes, compares references unless overridden.

  • Value Types: Generally compare values using their type-specific equality implementation.

  • Customization: Can be overridden to compare object properties.

  • Strings: Compare text content.

  • Null Safety: object.Equals(a, b) safely handles null arguments.

  • Hash Code: Override GetHashCode() when overriding equality.

  • Common Usage: Comparing objects based on business properties, such as Employee ID or Product Code.

 

3. What is ReferenceEquals() in C#?

ReferenceEquals() is a static method of the object class.

It determines whether two references point to the exact same object in memory.

Unlike == and Equals(), its behavior cannot be overridden or overloaded.

Example

public class Employee
{
    public int Id { get; set; }
}

Usage:

Employee emp1 = new Employee { Id = 101 };

Employee emp2 = emp1;

Employee emp3 = new Employee { Id = 101 };

Console.WriteLine(
    object.ReferenceEquals(emp1, emp2)); // True

Console.WriteLine(
    object.ReferenceEquals(emp1, emp3)); // False

Explanation

  1. emp1 references an Employee object.

  2. emp2 = emp1 copies the reference.

  3. Therefore, emp1 and emp2 point to the same object.

  4. emp3 references a separately created object.

  5. Even though emp3.Id is also 101, it is a different object.

Memory representation

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = emp1;
Employee emp3 = new Employee { Id = 101 };


   emp1         emp2              emp3
     |            |                 |
     +------+-----+                 |
            |                       |
            v                       v
    +---------------+       +---------------+
    | Employee      |       | Employee      |
    | Id = 101      |       | Id = 101      |
    +---------------+       +---------------+
        Object 1                 Object 2


ReferenceEquals(emp1, emp2) = True

ReferenceEquals(emp1, emp3) = False

What happens with value types?

int a = 10;
int b = 10;

Console.WriteLine(
    object.ReferenceEquals(a, b)); // False

Why?

Value types such as int are boxed when passed to ReferenceEquals().

Each argument is boxed into a separate object, so the references are different.

Key Points

  • Reference Comparison: Checks whether two references identify the same object.

  • Static Method: Called using object.ReferenceEquals().

  • Cannot Override: Its behavior cannot be customized.

  • Same Object: Returns true.

  • Different Objects: Returns false, even if their values are equal.

  • Value Types: Boxing usually results in separate objects, so direct value-type arguments return false.

  • Null: Returns true if both arguments are null.

  • Common Usage: Checking object identity and determining whether two references refer to the same instance.

 

4. Difference Between ==, Equals(), and ReferenceEquals()

Feature

==

Equals()

ReferenceEquals()

Type

Operator

Method

Static method

Comparison

Value or reference

Value or reference

Reference only

Default class behavior

Reference comparison

Reference comparison

Reference comparison

Value type comparison

Usually value

Usually value

Object identity after boxing

String comparison

Content

Content

Object identity

Can customize

Yes, overload

Yes, override

No

Can compare null

Yes, where supported

Static form is null-safe

Yes

Main purpose

General equality

Logical/value equality

Object identity

5. Complete Example – All Three Together

public class Employee
{
    public int Id { get; set; }

    public override bool Equals(object? obj)
    {
        return obj is Employee other &&
               Id == other.Id;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Usage:

Employee emp1 = new Employee { Id = 101 };

Employee emp2 = new Employee { Id = 101 };

Employee emp3 = emp1;

// == Operator
Console.WriteLine(emp1 == emp2); // False
Console.WriteLine(emp1 == emp3); // True

// Equals() Method
Console.WriteLine(emp1.Equals(emp2)); // True
Console.WriteLine(emp1.Equals(emp3)); // True

// ReferenceEquals() Method
Console.WriteLine(
    object.ReferenceEquals(emp1, emp2)); // False

Console.WriteLine(
    object.ReferenceEquals(emp1, emp3)); // True

Execution flow

             Compare Two Objects
                      |
          +-----------+-----------+
          |           |           |
          v           v           v
         ==        Equals()   ReferenceEquals()
          |           |           |
          v           v           v
     Operator      Equality      Object
     Behavior      Method        Identity
          |           |           |
          v           v           v
    Can Overload  Can Override  Cannot Override
          |           |           |
          v           v           v
     Value or     Value or       Same Object
     Reference    Reference      Reference?
 

6. Important Interview Scenarios

Scenario 1: Comparing two integers

int a = 100;
int b = 100;

Console.WriteLine(a == b);                  // True
Console.WriteLine(a.Equals(b));             // True
Console.WriteLine(object.ReferenceEquals(a, b)); // False

Reason: == and Equals() compare integer values, while ReferenceEquals() checks boxed object identity.

Scenario 2: Comparing two strings

string a = new string("Hello".ToCharArray());
string b = new string("Hello".ToCharArray());

Console.WriteLine(a == b);                  // True
Console.WriteLine(a.Equals(b));             // True
Console.WriteLine(object.ReferenceEquals(a, b)); // False

Reason: Both strings contain the same text but are different objects.

Scenario 3: Comparing objects using Employee ID

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = new Employee { Id = 101 };

Console.WriteLine(emp1.Equals(emp2)); // True

Reason: The overridden Equals() method compares the Id property instead of object identity.

Scenario 4: Checking whether two variables reference the same object

Employee emp1 = new Employee { Id = 101 };
Employee emp2 = emp1;

bool isSameObject =
    object.ReferenceEquals(emp1, emp2);

Console.WriteLine(isSameObject); // True

Reason: Both variables reference the same instance.

 

7. Important Interview Follow-up Questions

Q1. Does == always compare references for classes?

No. Classes can overload == to compare values. For example, string compares content.

Q2. Does Equals() always compare values?

No. For ordinary classes without an override, Object.Equals() uses reference equality.

Q3. Can we override ReferenceEquals()?

No. It is a static method whose behavior cannot be customized.

Q4. Why does ReferenceEquals() return false for two integers?

Because integers are boxed into separate objects when passed as arguments.

Q5. What is the difference between string.Equals() and ReferenceEquals()?

string.Equals() compares text content, whereas ReferenceEquals() checks whether both references point to the same string object.

Q6. What happens if we override Equals() but not GetHashCode()?

It violates the equality/hash-code contract and can cause incorrect behavior in hash-based collections such as Dictionary and HashSet.

Q7. Which should we use to compare two business objects?

Use Equals() with a properly implemented equality definition, or use an equality comparer, when logical equality is based on business properties.

 

Quick Interview Revision

Method

Remember

==

Operator-based equality

Equals()

Logical equality; can be overridden

ReferenceEquals()

Checks exact object identity

== for integers

Compares values

== for strings

Compares content

== for normal classes

Usually compares references

Equals() overridden

Can compare selected properties

ReferenceEquals()

Cannot be overridden

GetHashCode()

Must be consistent with Equals()

Interview Answer:

== is an equality operator whose behavior depends on the type and operator overloading. Equals() is a method that can be overridden to provide logical or value-based equality. ReferenceEquals() is a static method that checks whether two references point to exactly the same object. For ordinary classes, == and the default Equals() compare references, while overridden equality methods can compare object properties.

← Back to Articles