プロジェクトでハッシュ テーブルを使用する場合、GetHashCode をオーバーライドする必要がある場合があります。一般的なアプローチは次のとおりです:
バージョン 1:
ヘルパーを実装し、型 T を渡し、この型のハッシュコードを返します。関数のロジックは非常に単純で、null チェックを行うだけです。obj が空でない場合は、obj のハッシュ コードが直接使用されます。
public class HashHelper { private int _seed = 17; public int Hash<T>(T obj) { // why 31? // http://www.php.cn/ // shortly, to reduce the conflict of hashing key's distrabution return 31 * _seed + ((obj == null) ? -1 : obj.GetHashCode()); } }
なぜマジックナンバー 31 を使用するのでしょうか? 素数積を使用すると、相対的に一意性が向上し、ハッシュ キー値の割り当ての際の競合が軽減されますが、31 はコンパイラの最適化を考慮したものです (実質的に i< < 5-1 に変換されます)。調べてみると、この実装方法はJAVAの文字列のハッシュコード関数から来ています。詳細な紹介は次のとおりです:
https://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/
実装バージョン 2:
このクラスは次のように拡張できます。流暢なインターフェイス。さまざまな型をハッシュできます。値型の場合、オーバーロードの重要性はボックス化を軽減することであり、コレクションまたはジェネリックの場合、外部呼び出しをより自然で読みやすくすることです。
public class HashFluent { private int _seed = 17; private int _hashContext; public HashFluent Hash<T>(T obj) { // why 31? // http://www.php.cn/ // shortly, to reduce the conflict of hashing key's distrabution _hashContext = 31 * _seed + ((obj == null) ? -1 : obj.GetHashCode()); return this; } public HashFluent Hash(int? value) { _hashContext = 31 * _seed + ((value == null) ? -1 : value.GetHashCode()); return this; } public HashFluent Hash(IEnumerable sequence) { if (sequence == null) { _hashContext = 31 * _hashContext + -1; } else { foreach (var element in sequence) { _hashContext = 31 * _hashContext + ((element == null) ? -1 : element.GetHashCode()); } } return this; } public override int GetHashCode (){ return _hashContext; } // add more overridings here .. // add value types overridings to avoid boxing which is important }
上記は C# GetHashCode の実装の内容です。その他の関連内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。