hashcode
number hashing
coding tutorial
programming
algorithms

Create a hashcode of two numbers

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you need a hash code for two numbers, the goal is usually not cryptography. The real goal is to combine two values into one stable integer that works well in hash-based collections such as dictionaries, hash sets, or custom key types.

The important rule is that equal pairs must produce equal hash codes. Good distribution matters too, but correctness starts with matching the equality logic of the object or key you are hashing.

Use a Real Hash Combiner

In modern .NET, the simplest answer is HashCode.Combine. It already handles the mixing step for you.

csharp
1using System;
2using System.Collections.Generic;
3
4public readonly record struct PointKey(int X, int Y)
5{
6    public override int GetHashCode() => HashCode.Combine(X, Y);
7}
8
9var points = new Dictionary<PointKey, string>
10{
11    [new PointKey(10, 20)] = "first",
12    [new PointKey(30, 40)] = "second"
13};
14
15Console.WriteLine(points[new PointKey(10, 20)]);

That is usually the best choice because it is readable, correct, and harder to get wrong than a home-grown formula.

Manual Combination for Older Code

If you are on an older runtime or want to understand the mechanics, use a prime-based combiner.

csharp
1public static int Combine(int a, int b)
2{
3    unchecked
4    {
5        int hash = 17;
6        hash = hash * 31 + a;
7        hash = hash * 31 + b;
8        return hash;
9    }
10}
11
12Console.WriteLine(Combine(10, 20));
13Console.WriteLine(Combine(10, 21));

The unchecked block is intentional. Hash code arithmetic is allowed to overflow because the point is bit mixing, not preserving arithmetic meaning.

This pattern is common because multiplying by a prime and then adding the next field tends to distribute values better than naive formulas.

Do Not Confuse Hash Codes with Unique IDs

A hash code is not guaranteed to be unique. Different pairs can still collide.

That means a hash code should never be treated as:

  • a database primary key
  • a security token
  • proof that two inputs are different

Hash-based collections already know how to handle collisions by combining the hash code with equality checks. Your job is to provide a decent hash, not a mathematically unique fingerprint.

Avoid Weak Shortcuts

Some shortcuts look attractive but are poor choices:

  • 'a + b makes (1, 2) and (2, 1) identical'
  • string concatenation adds extra allocation and ambiguous formatting
  • bit shifting without care can lose too much information

For example, a * 1000 + b only works if you have rigid assumptions about the range of b, and those assumptions are easy to break later.

Using a real combiner keeps the intent clear and avoids hidden bugs when the valid number range changes.

Match Equality and Hashing

This is the contract that matters most: if two objects compare equal, they must return the same hash code.

csharp
1public sealed class Pair : IEquatable<Pair>
2{
3    public int A { get; }
4    public int B { get; }
5
6    public Pair(int a, int b)
7    {
8        A = a;
9        B = b;
10    }
11
12    public bool Equals(Pair? other) => other is not null && A == other.A && B == other.B;
13    public override bool Equals(object? obj) => obj is Pair other && Equals(other);
14    public override int GetHashCode() => HashCode.Combine(A, B);
15}

If equality uses both A and B, the hash must also use both. Leaving one field out creates broken behavior in dictionaries and sets.

Common Pitfalls

The biggest mistake is expecting a hash code to be unique for every pair of numbers. Collisions are normal and must be tolerated.

Another common problem is using an overly simple formula such as plain addition or concatenated strings. Those produce poor distribution and unnecessary collisions.

It is also easy to forget the equality contract. If equality checks two fields but the hash uses only one, hash-based collections behave incorrectly.

Finally, do not use ordinary hash codes for cryptographic or security-sensitive work. A collection hash and a secure hash solve completely different problems.

Summary

  • Use HashCode.Combine(a, b) in modern .NET when possible.
  • A manual prime-based combiner is a reasonable fallback.
  • Hash codes are not unique identifiers and collisions are expected.
  • Make sure the hash uses the same fields as equality.
  • Avoid simplistic formulas that collapse many pairs into the same value.

Course illustration
Course illustration

All Rights Reserved.