Why is it important to override GetHashCode() with Equals() in C#

In C#, when dealing with hash-based data structures like hash tables, dictionaries, and sets, we rely on two methods: GetHashCode() and Equals(). The GetHashCode() method creates a unique code for each item in these data structures, while the Equals() method is used to check if two objects are the same.

Importance

Overriding both the GetHashCode() and Equals() methods together is essential to ensure consistent behavior. When two objects are considered equal based on the Equals() method, their hash codes must be identical. Unexpected behavior and performance concerns may occur if the GetHashCode() method is improperly overridden while storing and retrieving objects from hash-based collections.

Default implementation of GetHashCode()

The Object class’s default implementation, which generates the hash code using the object’s reference address, will be applied if the GetHashCode() method is not overridden. In this scenario, two objects with different memory addresses but containing the same data will have different hash codes, leading to inaccurate behavior when used in hash-based collections.

Customized hashing technique

We develop a customized hashing technique by overriding the GetHashCode() method that considers the pertinent features of the object. As a result, objects with identical data will generate the same hash code, allowing for proper storing and retrieval from hash-based collections.

Code example

Let’s say that we have a class Student that represents a student with a name, roll no. and age:

using System;
public class Student
{
public string Name { get; }
public int RollNo { get; }
public int Age { get; }
public Student(string name, int rollno, int age)
{
Name = name;
RollNo = rollno;
Age = age;
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
Student otherStudent = (Student)obj;
return Name == otherStudent.Name && RollNo == otherStudent.RollNo && Age == otherStudent.Age;
}
public override int GetHashCode()
{
int hash = 11;
hash = hash * 18 + Name.GetHashCode();
hash = hash * 18 + RollNo.GetHashCode();
hash = hash * 18 + Age.GetHashCode();
return hash;
}
}
public class Program
{
public static void Main()
{
Student student1 = new Student("John Doe", 1001, 25);
Student student2 = new Student("Bob Smith", 1002, 30);
Student student3 = new Student("John Doe", 1001, 25);
Console.WriteLine($"student1 and student2 are equal: {student1.Equals(student2)}");
Console.WriteLine($"student1 and student3 are equal: {student1.Equals(student3)}");
Console.WriteLine($"HashCode of student1: {student1.GetHashCode()}");
Console.WriteLine($"HashCode of student2: {student2.GetHashCode()}");
Console.WriteLine($"HashCode of student3: {student3.GetHashCode()}");
}
}

Code explanation

  • Lines 3–14: We define a Student class with three properties: Name, RollNo, and Age. The class also includes a constructor to initialize these properties.

  • Lines 16–23: The Equals() method is overridden in the Student class. It checks if the passed object is not null and is of the same type as Student. If not, it returns false immediately. Otherwise, it casts the object to a Student type and compares its Name, RollNo, and Age properties with the current instance’s properties. If all three properties match, the objects are considered equal, and true is returned; otherwise, false is returned.

  • Lines 25–32: The GetHashCode() method is also overridden. It generates a hash code based on the Name, RollNo, and Age properties of the Student object. A straightforward hashing method combines these values into a single hash code.

  • Lines 39–41: Three Student class instances—student1, student2, and student3—are created in the Main() method. In terms of data, student1 and student3 are identical because they share the same Name, RollNo, and Age characteristics.

  • Line 43: Student1 and Student2 are compared using the Equals() method, with the outcome being reported to the console. Since they have different data, it will be false.

  • Line 44: Student1 and Student3 are also compared using the Equals() method, with the results being written to the console. They share the same data; therefore, it will be true.

  • Lines 46–48: Each Student instance receives a call to the GetHashCode() function, and the hash codes returned are reported to the console. Student1 and Student3 will share the same hash code because their data is identical.

Conclusion

In summary, overriding the GetHashCode() method alongside the Equals() method is essential to maintaining consistency when working with hash-based collections and to ensure that objects with the same data are considered equal and produce the same hash code.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved