GetHashCode Guidelines in C
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
GetHashCode matters whenever an object is used in Dictionary<TKey, TValue>, HashSet<T>, or any other hash-based collection. The method does not need to produce a unique number for every object, but it must follow strict consistency rules with equality or the collection will behave incorrectly.
The First Rule Is Consistency with Equals
If two objects are equal according to Equals, they must return the same hash code. This is not an optimization guideline; it is a correctness requirement.
If Equals compares FirstName and LastName, then GetHashCode must use the same identity-defining fields. Using only one of them would increase collisions and could break lookup behavior when equality says two objects are different.
Equal Objects Must Stay Stable While in a Hash Collection
A hash code can change only if the equality-defining state changes. In practice, that means objects used as dictionary keys should usually be immutable.
If Person were mutable and one of its key fields changed after insertion, the object could end up in the wrong bucket. Then Contains or Remove might fail even though the object is still physically present in the set.
Do Not Treat Hash Codes as Permanent IDs
A hash code is not a stable external identifier. Different runs of an application can produce different hash codes for the same logical value, especially for framework types such as string. Hash codes are for in-memory hashing, not for persistence, database keys, or cross-process protocols.
That means you should never serialize a hash code and expect it to remain meaningful later.
Prefer HashCode.Combine in Modern C#
Older examples often use manual multiplication with prime numbers. That still works, but modern .NET provides HashCode.Combine, which is clearer and less error-prone.
If your type has many fields, combining the fields that actually participate in equality is usually enough. Do not include every property by reflex. Include only the ones that define object identity.
Value Objects and Reference Identity Are Different
Not every class should override GetHashCode. If reference identity is the intended behavior, the base implementation may be correct. Override GetHashCode when the type has value semantics and you are also overriding Equals.
This is a classic value object. Two Money instances with the same amount and currency should behave as equal values in dictionaries and sets.
Collisions Are Allowed, but Bad Distribution Hurts Performance
Different objects may share the same hash code. That is normal. The goal is not uniqueness; it is a reasonably even distribution. Poor distribution leads to more collisions and slower lookups because more equality comparisons are needed within the same bucket.
What you should avoid is simplistic implementations such as returning a constant or hashing only the first field of a multi-field key.
Common Pitfalls
- Overriding
Equalswithout overridingGetHashCodeto match it. - Using mutable fields in the hash code for objects that will live in dictionaries or sets.
- Treating hash codes as persistent identifiers or data that should survive across program runs.
- Including fields in
GetHashCodethat are not part of logical equality, or omitting fields that are. - Returning overly simplistic values that cause unnecessary collisions.
Summary
- '
GetHashCodemust agree withEqualsfor all equal objects.' - Types used as hash keys should usually be immutable with respect to equality-defining fields.
- Hash codes are for in-memory hashing, not for storage or external identity.
- '
HashCode.Combineis the preferred modern implementation style in C#.' - Good hash codes do not need to be unique, but they should distribute values reasonably well.
Related reading
- GetPathsOfAllDirectoriesAbove cannot be evaluated after updating .Net Framework version 4.6.2 to 4.7.2
- GetProperties to return all properties for an interface inheritance hierarchy
- Getter and Setter declaration in .NET
- Getting a 2nd IAsyncEnumerator from the same IAsyncEnumerable based on Task.WhenEach method
- Getting all types in a namespace via reflection
- Getting assembly name
- Getting current directory in .NET web application
- Getting day suffix when using DateTime.ToString

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.