【.NET】Object.GetHashCodeの結果は実際結構被る

.NETのObject.GetHashCodeの結果は実際結構被るというお話です。

Object.GetHashCode()

C#にはオブジェクトのハッシュ値を返すGetHashCode()というメソッドがあります。

docs.microsoft.com

これの仕様として、同じオブジェクトであればこの値は同じものを返します。
しかしながら、この値が同じであっても同じオブジェクトであるとは限りません。

要するに違うオブジェクトであってもGetHashCode()の結果は被る可能性があります。

そこで、実際問題どのくらい被るんだろうと思い調べてみました。

実際どれくらい被るのか

今回は文字列のGetHashCode()メソッドについて調べてみます。
実装は以下の通りです。

using System;
using System.Collections.Generic;
using System.Linq;

public class Example
{
    private static void Test()
    {
        var duplicateCounts = new int[100];

        // 100回試す
        for (var i = 0; i < 100; i++)
        {
            // 100000個の文字列のGetHashCodeの被り回数をしらべる
            var sources = new HashSet<string>();
            var hashCodes = new HashSet<int>();
            for (var j = 0; j < 100000; j++)
            {
                var source = Guid.NewGuid().ToString();
                if (!sources.Add(source))
                {
                    throw new Exception("sourceが被った");
                }
                hashCodes.Add(source.GetHashCode());
            }

            duplicateCounts[i] = sources.Count - hashCodes.Count;
        }
        
        var ave = duplicateCounts.Average(); // だいたい1ちょい
    }
}

コメントにも書きましたが、だいたい100000回に1回くらいは被ることが確認できました。