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
Studentclass with three properties:Name,RollNo, andAge. The class also includes a constructor to initialize these properties. -
Lines 16–23: The
Equals()method is overridden in theStudentclass. It checks if the passed object is not null and is of the same type asStudent. If not, it returnsfalseimmediately. Otherwise, it casts the object to aStudenttype and compares itsName,RollNo, andAgeproperties with the current instance’s properties. If all three properties match, the objects are considered equal, andtrueis returned; otherwise,falseis returned. -
Lines 25–32: The
GetHashCode()method is also overridden. It generates a hash code based on theName,RollNo, andAgeproperties of theStudentobject. A straightforward hashing method combines these values into a single hash code. -
Lines 39–41: Three
Studentclass instances—student1,student2, andstudent3—are created in theMain()method. In terms of data,student1andstudent3are identical because they share the sameName,RollNo, andAgecharacteristics. -
Line 43:
Student1andStudent2are compared using theEquals()method, with the outcome being reported to the console. Since they have different data, it will befalse. -
Line 44:
Student1andStudent3are also compared using theEquals()method, with the results being written to the console. They share the same data; therefore, it will betrue. -
Lines 46–48: Each
Studentinstance receives a call to theGetHashCode()function, and the hash codes returned are reported to the console.Student1andStudent3will 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