0

私は単純な 2D 環境を開発しており、描画された各オブジェクト (線、四角形など) は、GetHashCode() を呼び出して一意の ID を取得します。

ここで、 MSDN ページで、その結果が一意であるとは限らないことに気付きました。

GetHashCode メソッドの既定の実装では、異なるオブジェクトに対して一意の戻り値が保証されるわけではありません。さらに、.NET Framework は GetHashCode メソッドの既定の実装を保証しておらず、返される値は .NET Framework の異なるバージョン間で同じになります。したがって、このメソッドのデフォルトの実装は、ハッシュ目的で一意のオブジェクト識別子として使用しないでください。

さて、問題は、メソッド以外にどのようなオプションが存在するかというGetHashCode()ことです?

ありがとう、アミット

4

4 に答える 4

3

おそらく、ハッシュコードから完全に離れることが最善でしょうか?GetHashCodeすばやく簡単に修正するには便利ですが、オブジェクトに実際のIDが必要な場合は、実際のIDを作成する必要があります。32/64ビットの自動インクリメント整数のようなもので十分でしょう。

ハッシュコードの衝突率はハッシュの長さに関係していますが、衝突が発生する前に可能な一意のハッシュの最大数に到達することは保証されていません。IDを自分で管理する場合は、十分なIDを使用できるように事前に計画することができます。

また、フレームワークのバージョン間で異なるGetHashCode()に関するコメント。ある種の保存ファイルにハッシュを保持し、保存されたために実行中のプログラムのハッシュと一致しないことを確認するためだけにハッシュを再ロードしようとした場合にのみ、これが問題になると想像できます。フレームワークの異なるバージョンによって。その場合は、オブジェクトのIDを自分で作成して管理することをお勧めします。

于 2012-09-29T01:36:54.823 に答える
3

独自のIDを生成する必要があります

オブジェクトに自然キーがある場合、オブジェクトのプロパティから一意のIDを取得できる場合があります。
オブジェクトに自然キーがない場合は、一意のIDを生成する必要があり、通常、コンストラクターでオブジェクトに一意のIDを渡します。

GetHashCodeは、一意であることが保証されていないため、一意のIDとしては不十分です。
内部的には、.NETは一意性のためにGetHashCodeを使用しません。
内部的には、.NETはGetHashCodeを使用して、同等性の比較とHashBucketsを高速化します。

独自の一意のIDを生成する場合は、GetHashCodeとEqualsをオーバーライドする必要があります。
そうすれば、.NETは一意の識別子を使用して同等性を比較できます。

.NET GetHashCode()は必須ではなく、一意であることが保証されていません。
.NET GetHashCode()は、Int32だけに限定されません。
.NET GetHashCode()はInt32です。

GetHashCodeが等しくない場合、2つのオブジェクトは等しくありません。
GetHashCodeが等しい場合、2つのオブジェクトは等しい場合と等しくない場合があります。Equalsはタイブレーカーです。
速度については、最初にGetHashCodeが比較されます。GetHashCodeは、HashSetやDictionaryなどのコレクションを高速化するためのハッシュバケットにも使用されます。

ハッシュが一意である場合、それは完全なハッシュと見なされます。

古典的な例

class Point: object 
{
   protected int x, y;

   public Point(int xValue, int yValue)
   {
        x = xValue;
        y = yValue;
   }
   public override bool Equals(Object obj) 
   {
      // Check for null values and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) 
         return false;

      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }
   public override int GetHashCode() 
   {
      return x ^ y;
   }
}

PointにはInt32XInt32の可能な値があるため、単一のInt32で一意に識別できないことは明らかです。それでもGetHashCodeは価値があり、必須です。より高価なEqualsが必要になる可能性は1/Int32のみであり、GetHashCodeがハッシュバケットに使用されます。

簡単なポイントを考えてみましょう

class Point: object 
{
   protected byte x, y;

   public Point(byte xValue, byte yValue)
   {
        x = xValue;
        y = yValue;
   }
   public override bool Equals(Object obj) 
   {
      // Check for null values and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) 
         return false;

      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }
   public override int GetHashCode() 
   {
      return (x * 256) + y;
   }
}

この単純な点で、GetHashCodeはオブジェクトを一意に識別します。他のいずれかをオーバーライドすることはできません。どちらも、または両方をオーバーライドする必要があります。

于 2012-09-29T01:37:13.947 に答える
2

一意の ID を何に使用しているかによって異なります。オブジェクト インスタンスを識別するために使用しているように思えます。これは、ハッシュ コードが必要なものではないことを意味している可能性があります。

2 つのオブジェクトが互いに .Equals() である場合、それらは同じハッシュ コードを持っているはずですが、ご存じのように、逆は当てはまりません (同じハッシュ コードを持っていても、それらが .Equals() であるとは限りません)。

一意の ID は何のために必要ですか? ハッシュ コードを使用してオブジェクトを検索しない場合は、Guid ( var uniqueId = Guid.NewGuid()) のような一意の ID を割り当てる方がよい場合があります。

于 2012-09-29T01:39:56.890 に答える
1

返される値の一意性を保証するハッシュ関数はありません。

衝突の可能性がどれだけ小さいかによって異なります。

GetHashCode() は 32 ビット整数を返しますが、これは一意性を仮定するには不十分な場合があります。ハッシュの長さが長い SHA-1、SHA-2 などの他のアルゴリズムを検討してください。衝突の確率は 32 ビット整数よりもはるかに低くなります。

于 2012-09-29T01:26:46.493 に答える