この記事は機械翻訳されています。英語版の記事を表示するには、[英語] のチェック ボックスをオンにしてください。また、テキストにマウス ポインターを合わせると、ポップアップ ウィンドウに英語のテキストを表示することもできます。
翻訳
英語

Object.GetHashCode メソッド ()

 

公開日: 2016年11月

既定のハッシュ関数として機能します。

名前空間:   System
アセンブリ:  mscorlib (mscorlib.dll 内)

public virtual int GetHashCode()

戻り値

Type: System.Int32

現在のオブジェクトのハッシュ コード。

ハッシュ コードを挿入し、などハッシュ ベースのコレクション内のオブジェクトの識別に使用される数値の値は、Dictionary<TKey, TValue>クラス、Hashtableクラスから派生した型、または、DictionaryBaseクラスです。 GetHashCodeメソッドは、アルゴリズムを迅速にオブジェクトの等価性の確認を必要とするためこのハッシュ コードを提供します。

System_CAPS_noteメモ

ハッシュ テーブルのハッシュ コードを使用する方法に関する情報といくつか追加のハッシュ コードのアルゴリズムを参照してください、 Hash Function Wikipedia で入力します。

等しいと同じ戻り値のハッシュ コードは、2 つのオブジェクト。 ただし、この逆はできません。 同じハッシュ コードを意味しませんオブジェクトの等価性 (等しくない) 別のオブジェクトが同一のハッシュ コードを持てないためです。 さらに、.NET Framework とは限りませんの既定の実装、GetHashCodeメソッド、および、このメソッドから返される値が異なる .NET Framework のバージョンとプラットフォームでは、32 ビットおよび 64 ビットのプラットフォームなどの間です。 これらの理由から、このメソッドの既定の実装固有のオブジェクト識別子としてに使わないハッシュの目的でします。 これから次の 2 つの影響。

  • 同じハッシュ コードがオブジェクトの等価性を示すものであると想定する必要があります。

  • 永続化したり、同じオブジェクトをアプリケーション ドメイン、プロセス、およびプラットフォーム間でハッシュ可能性がありますのでが作成されたアプリケーション ドメインの外部ハッシュ コードを使用する必要がありますしないでください。

System_CAPS_warning警告

ハッシュ コードは、効率的な挿入とハッシュ テーブルに基づいているコレクション内の参照です。 ハッシュ コードは、永続的な値ではありません。 このため。

  • ハッシュ コード値をシリアル化したり、データベースに格納しないでください。

  • キー付きのコレクションからオブジェクトを取得するのに、キーとしてハッシュ コードを使用しません。

  • アプリケーション ドメインまたはプロセス間では、ハッシュ コードを送信しません。 場合によっては、プロセスごとまたはアプリケーションごとのドメインごとにハッシュ コードを計算することがあります。

  • 暗号強度が高いハッシュする必要がある場合は、暗号ハッシュ関数によって返される値ではなくハッシュ コードを使用しません。 暗号法のハッシュから派生するクラスを使用して、System.Security.Cryptography.HashAlgorithmまたはSystem.Security.Cryptography.KeyedHashAlgorithmクラスです。

  • 2 つのオブジェクトが等しいかどうかを判断するハッシュ コードの等価性をテストしません。 (等しくないオブジェクトは、同一のハッシュ コードを持つことができます) 等しいかどうかをテストするには、呼び出し、ReferenceEqualsまたはEqualsメソッドです。

GetHashCode派生型でメソッドをオーバーライドすることができます。 場合GetHashCodeがオーバーライドされていないハッシュ コードを呼び出すことによって計算が参照型、Object.GetHashCodeハッシュ コードを計算する、基本クラスのメソッド ベース以外のオブジェクトの参照の詳細についてを参照してくださいRuntimeHelpers.GetHashCodeです。 つまり、2 つのオブジェクトをReferenceEqualsメソッドを返します。true同一のハッシュ コードがあります。 値の型をオーバーライドしない場合GetHashCodeValueType.GetHashCode基底クラスのメソッドでは、リフレクションを使用して、型のフィールドの値に基づいてハッシュ コードを計算します。 つまり、その結果、フィールドが同じ値を持つ値型では、同じハッシュ コードがあります。 オーバーライドの詳細についてはGetHashCode、「ノート継承クラス」を参照してください。

System_CAPS_warning警告

オーバーライドする場合、GetHashCodeメソッドもオーバーライドするEquals、およびその逆です。 場合、オーバーライドされたEqualsメソッドを返します。true等しいかどうかを、オーバーライドされた 2 つのオブジェクトをテストするときにGetHashCodeメソッドは、2 つのオブジェクトに対して同じ値を返す必要があります。

ハッシュ テーブル内のキーとして使用されるオブジェクトがに役立ちます実装を提供していないかどうかGetHashCode、ハッシュ コード プロバイダーを指定するには指定することによって、IEqualityComparer実装のオーバー ロードのいずれかに、Hashtableクラスのコンス トラクターです。

呼び出すと、GetHashCode内のクラスのメソッド、 Windows ランタイム、しないをオーバーライドするクラスの既定の動作を提供GetHashCodeです。 これは、.NET Framework が Windows ランタイムに提供するサポートの一部です (「Windows ストア アプリおよび Windows ランタイムのための .NET Framework サポート」を参照してください)。 内のクラス、Windows ランタイム継承しないObject、現在実装していないと、GetHashCodeです。 ただし、それらがように見えますToStringEquals(Object)、およびGetHashCodeメソッド、c# または Visual Basic コードで使用すると、.NET Framework では、これらのメソッドの既定の動作です。

System_CAPS_noteメモ

Windows ランタイムc# または Visual Basic で記述されたクラスをオーバーライドして、GetHashCodeメソッドです。

継承時の注意:

ハッシュ関数を使用して、すばやくオブジェクトの値に対応する番号 (ハッシュ コード) を生成します。 ハッシュ関数は通常、各種類に固有しが、一意である必要があります少なくとも 1 つのインスタンス フィールドの入力として使用します。 ハッシュ コードは、静的フィールドの値を使用していない計算する必要があります。

派生したクラスのObjectGetHashCodeメソッドは、基底クラスに委任できますObject.GetHashCode()派生クラスには参照の等価性に等しいかどうかが定義されている場合にのみ実装されます。 既定の実装GetHashCode参照の種類がによって返されたと等価のハッシュ コードを返します、RuntimeHelpers.GetHashCode(Object)メソッドです。 オーバーライドできますGetHashCode変更不可の参照の種類。 一般に、変更可能な参照型の場合は、オーバーライドするGetHashCode場合のみ。

  • 変更できません。 指定されたフィールドのハッシュ コードを計算することができます。または

  • オブジェクトがそのハッシュ コードに依存しているコレクションに含まれている間に、変更可能なオブジェクトのハッシュ コードが変更されないことを確認することができます。

それ以外の場合、ハッシュ テーブルで変更可能なオブジェクトが失われることを検討する可能性があります。 オーバーライドする場合はGetHashCode変更可能な参照型の場合は、ドキュメント必要があることを明示するため、オブジェクトが、ハッシュ テーブルに格納されているときに、型のユーザーがオブジェクトの値を変更しないでください。

値型の場合は、ValueType.GetHashCodeリフレクションを使用する既定のハッシュ コード実装を提供します。 パフォーマンス向上のためにオーバーライドすることを検討する必要があります。

System_CAPS_noteメモ

詳細とさまざまな方法でのハッシュ コードを計算する例については、「例」を参照してください。

ハッシュ関数では、次のプロパティが必要です。

  • 2 つのオブジェクトが等しいかどうか、として比較している場合、GetHashCodeの各オブジェクトのメソッドは、同じ値を返す必要があります。 ただし、2 つのオブジェクトが等しいかどうか、として比較されない場合、 GetHashCode 2 つのオブジェクトのメソッドは、異なる値を返す必要はありません。

  • GetHashCodeメソッドは、オブジェクトがオブジェクトの戻り値を決定するオブジェクトの状態への変更がない限り、同じハッシュ コードを返す必要があります一貫してEqualsメソッドです。 アプリケーションの現在の実行にのみ true であるし、アプリケーションをもう一度実行する場合は別のハッシュ コードを返されることができますに注意してください。

  • ハッシュ関数では最適なパフォーマンスを大きくがクラスター化されている入力を含む、すべての入力に対して均等な分布が生成されます。 オブジェクトの状態に変更を加える必要がありますになる大きなハッシュ テーブルの最適なパフォーマンスの結果のハッシュ コード変更では、します。

  • ハッシュ関数を計算する高価なすることはできません。

  • GetHashCodeメソッドが例外をスローする必要があります。

たとえばの実装、GetHashCodeによって提供されるメソッド、Stringクラスはまったく同じ文字列値の同一のハッシュ コードを返します。 そのため、2 つStringオブジェクトが同じ文字列値を表している場合、同じハッシュ コードを返します。 また、メソッドを使用してすべての文字文字列の入力が特定の範囲にクラスター化された場合でも、ある程度ランダムに分散型の出力を生成する (たとえば、多くのユーザーがある、下位 128 ASCII 文字のみを含む文字列 65,535 の Unicode 文字のいずれかの文字列が含まれていても)。

クラスの適切なハッシュ関数を提供することができます著しく影響する場合、ハッシュ テーブルへのそれらのオブジェクトの追加のパフォーマンスです。 ハッシュ関数の適切な実装を提供するキーを持つハッシュ テーブルでは、要素の検索と、(たとえば、o (1) 操作) 定数時間がかかります。 ハッシュ関数の不適切な実装でハッシュ テーブルの検索のパフォーマンスによって異なります、ハッシュ テーブル内の項目数 (たとえば、O (n) 操作、場所nハッシュ テーブル内の項目の数です)。 悪意のあるユーザーは、次の条件下で、ハッシュ テーブルに依存するアプリケーションのパフォーマンスが大幅に低下の衝突の数が増加するデータを入力できます。

  • ときにハッシュ関数は、頻繁に競合を作成します。

  • ときに、ハッシュ テーブル内のオブジェクトの大部分が等しいか、互いにほぼ同じ数のハッシュ コードを生成します。

  • ときにユーザーは、ハッシュ コードの計算元となるデータを入力します。

オーバーライドするクラスを派生GetHashCodeもオーバーライドしなければなりませんEquals等しいと見なされる 2 つのオブジェクトに同じハッシュ コードがあることを保証するためにそれ以外の場合、Hashtable型が正しく動作しません。

ハッシュ コードを同じか、またはより小さい範囲を持つ数値を計算する最も簡単な方法の 1 つ、Int32型が単純にその値を返すにします。 次の例では、このような実装、Number構造体。

using System;

public struct Number
{
   private int n;

   public Number(int value)
   {
      n = value;
   }

   public int Value
   {
      get { return n; }
   }

   public override bool Equals(Object obj)
   {
      if (obj == null || ! (obj is Number)) 
         return false;
      else
         return n == ((Number) obj).n;
   }      

   public override int GetHashCode()
   {
      return n;
   }

   public override string ToString()
   {
      return n.ToString();
   }
}

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      for (int ctr = 0; ctr <= 9; ctr++) {
         int randomN = rnd.Next(Int32.MinValue, Int32.MaxValue);
         Number n = new Number(randomN);
         Console.WriteLine("n = {0,12}, hash code = {1,12}", n, n.GetHashCode());
      }   
   }
}
// The example displays output like the following:
//       n =   -634398368, hash code =   -634398368
//       n =   2136747730, hash code =   2136747730
//       n =  -1973417279, hash code =  -1973417279
//       n =   1101478715, hash code =   1101478715
//       n =   2078057429, hash code =   2078057429
//       n =   -334489950, hash code =   -334489950
//       n =    -68958230, hash code =    -68958230
//       n =   -379951485, hash code =   -379951485
//       n =    -31553685, hash code =    -31553685
//       n =   2105429592, hash code =   2105429592

多くの場合、型では、ハッシュ コードの生成に含めることができる複数のデータ フィールドがあります。 使用してこれらのフィールドを結合するにはハッシュ コードを生成する方法、XOR (eXclusive OR)操作、次の例で示すようにします。

using System;

// A type that represents a 2-D point.
public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (! (obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return x ^ y;
    } 
} 

public class Example
{
   public static void Main()
   {
      Point pt = new Point(5, 8);
      Console.WriteLine(pt.GetHashCode());

      pt = new Point(8, 5);
      Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       13
//       13

前の例は、(n1、n2) に対して同じハッシュ コードを返します (n2、n1)、および、要件を満たしているよりも多くの競合を生成する可能性があります。 ソリューションの数は、このような場合のハッシュ コードが同じでないようにに利用可能なされます。 1 つのハッシュ コードを返すには、Tupleの各フィールドの順序を反映するオブジェクト。 次の例では、使用可能な実装、Tuple<T1, T2>クラスです。 ただしをインスタンス化のパフォーマンスのオーバーヘッド、Tupleオブジェクトは、ハッシュ テーブルに多数のオブジェクトを格納するアプリケーションの全体的なパフォーマンスに大きく影響可能性があります。

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return Tuple.Create(x, y).GetHashCode();
    } 
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       173
//       269

2 番目の代替ソリューションには、連続するフィールドのハッシュ コードを 2 つ以上のビットを左シフトして個々 のハッシュ コードを重み付けが含まれます。 最適に、破棄されるのではなくビット 31 を超えてシフトをラップするではなくは破棄されます。 C# および Visual Basic の両方で左シフト演算子では、ビットが破棄され、以降は、次のように左 shift キーを押し、ラップ メソッドを作成する必要があります。

public int ShiftAndWrap(int value, int positions)
{
    positions = positions & 0x1F;

    // Save the existing bit pattern, but interpret it as an unsigned integer.
    uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
    // Preserve the bits to be discarded.
    uint wrapped = number >> (32 - positions);
    // Shift and wrap the discarded bits.
    return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}

次の例は、のハッシュ コードを計算するこのシフトの折り返し方法を使用して、Point前の例で使用される構造体。

using System;

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return ShiftAndWrap(x.GetHashCode(), 2) ^ y.GetHashCode();
    } 

    private int ShiftAndWrap(int value, int positions)
    {
        positions = positions & 0x1F;

        // Save the existing bit pattern, but interpret it as an unsigned integer.
        uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
        // Preserve the bits to be discarded.
        uint wrapped = number >> (32 - positions);
        // Shift and wrap the discarded bits.
        return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
    }
} 

public class Example
{
   public static void Main()
   {
        Point pt = new Point(5, 8);
        Console.WriteLine(pt.GetHashCode());

        pt = new Point(8, 5);
        Console.WriteLine(pt.GetHashCode());
   }
}
// The example displays the following output:
//       28
//       37 

ユニバーサル Windows プラットフォーム
8 以降で使用可能
.NET Framework
1.1 以降で使用可能
ポータブル クラス ライブラリ
サポート対象: 移植可能 .NET プラットフォーム
Silverlight
2.0 以降で使用可能
Windows Phone Silverlight
7.0 以降で使用可能
Windows Phone
8.1 以降で使用可能
トップに戻る
表示: