2

次のコードを検討してください。

byte[] bytes = new byte[] { 1, 2, 5, 0, 6 };
byte[] another = new byte[] { 1, 2, 5, 0, 6 };

Hashtable ht = new Hashtable();
ht.Add(bytes, "hi");
Assert.IsTrue(ht.ContainsKey(another));

このアサーションが失敗するのはなぜですか?プリミティブ型の配列であることは、オブジェクト参照を使用するべきではありませんか?では、なぜそれはfalseを返すのでしょうか?このハッシュテーブルを機能させるために私にできることはありますか?

4

4 に答える 4

7

プリミティブ型の配列であることは、オブジェクト参照を使用するべきではありませんか?

はい、そうすべきです。配列は参照型です。

すべてが想定どおりに機能しています。

別の動作が必要な場合は、内容を比較してハッシュテーブルに渡す配列のコンパレータを実装できます。

于 2009-12-15T03:48:44.750 に答える
4

実装例は次のとおりです。

  class Program {
    static void Main(string[] args) {
      byte[] bytes = new byte[] { 1, 2, 5, 0, 6 };
      byte[] another = new byte[] { 1, 2, 5, 0, 6 };

      Hashtable ht = new Hashtable(new ByteArrayComparer());
      ht.Add(bytes, "hi");
      System.Diagnostics.Debug.Assert(ht.ContainsKey(another));
    }

    private class ByteArrayComparer : IEqualityComparer {
      public int GetHashCode(object obj) {
        byte[] arr = obj as byte[];
        int hash = 0;
        foreach (byte b in arr) hash ^= b;
        return hash;
      }
      public new bool Equals(object x, object y) {
        byte[] arr1 = x as byte[];
        byte[] arr2 = y as byte[];
        if (arr1.Length != arr2.Length) return false;
        for (int ix = 0; ix < arr1.Length; ++ix)
          if (arr1[ix] != arr2[ix]) return false;
        return true;
      }
    }
  }

ハッシュ テーブルに何千もの配列を配置する場合は、より強力なハッシュを使用する必要があります。例については、この投稿を確認してください。

于 2009-12-15T04:27:03.813 に答える
0

デフォルトでは、参照型は、その型のEqualsメソッドがオーバーライドされていない限り、参照によって比較されます。

参照型をhasテーブルのキーとして使用するため、GetHashCodeメソッドもオーバーライドして、「等しい」オブジェクトが同じハッシュコードを生成するようにする必要があります。

ハッシュテーブルは、GetHashCodeメソッドを使用してハッシュを計算することによってオブジェクトを格納し、それ以降の「ヒット」はこれを使用して計算されます。これを行うには、GetHasshCodeによって返される値を、オブジェクトの各プロパティ(この場合は配列内の各バイト)に基づいて計算します。これは私が使用した例です。ハッシュテーブルで使用できるIEqualityComparerでもこれを実行できます。

 public override int GetHashCode() {
        int hash = 17;
  hash = hash * 23 + DrillDownLevel.GetHashCode();
  hash = hash * 23 + Year.GetHashCode();

  if (Month.HasValue) {
    hash = hash * 23 + Month.Value.GetHashCode();
  }

  if (Week.HasValue) {
    hash = hash * 23 + .Week.Value.GetHashCode();
  }

  if (Day.HasValue) {
    hash = hash * 23 + obj.Day.Value.GetHashCode();
  }

  return hash;
}
于 2009-12-15T04:01:55.867 に答える
0

ハッシュが一致しないため、false を返します。GetHashCode() が同じ値に対して繰り返し可能なハッシュを生成しない場合、辞書では機能しません。

byte[] bytes = new byte[] { 1, 2, 5, 0, 6 };
byte[] another = new byte[] { 1, 2, 5, 0, 6 };

string astring = "A string...";
string bstring = "A string...";

MessageBox.Show(bytes.GetHashCode() + " " + another.GetHashCode() + " | " + astring.GetHashCode() + " " + bstring.GetHashCode());
于 2009-12-15T03:53:28.147 に答える