Warum wird nicht ein Hashtable return true für „ContainsKey“ für einen Schlüssel vom Typ byte [] in C #?

StackOverflow https://stackoverflow.com/questions/1905038

  •  19-09-2019
  •  | 
  •  

Frage

Betrachten Sie den folgenden Code ein:

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));

Warum versagen diese Behauptung? ein Array von einem primitiven Typ zu sein, sollte nicht den Objektverweis verwenden verwenden, soll es? Also warum sollte es false zurück? Gibt es etwas, was ich tun kann diese hashtable Arbeit zu machen?

War es hilfreich?

Lösung

Hier ist eine Beispielimplementierung:

  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;
      }
    }
  }

Sie sollten eine stärkere Hash verwenden, wenn Sie Tausende von Arrays in der Hash-Tabelle setzen. Prüfen Sie diesen Beitrag für ein Beispiel.

Andere Tipps

  

ein Array von einem primitiven Typ zu sein, sollte nicht den Objektverweis verwenden verwenden, soll es?

Ja es sollte. Arrays sind Referenztypen.

Alles funktioniert wie es sollte.

Wenn Sie ein anderes Verhalten möchten, können Sie einen Komparator für Arrays implementieren, die den Inhalt vergleicht und übergeben, die mit dem Hash-Tabelle.

Es gibt false zurück, weil der Hashes nicht übereinstimmen. Wenn GetHashCode () keine wiederholbaren Hash für den gleichen Wert erzeugen wird es nicht funktionieren in einem Wörterbuch.

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());

Mit dem Standardreferenztypen zeichnen sich durch ihre Referenzen verglichen, es sei denn, die Methode Equals für diese Art außer Kraft gesetzt wurde.

Da Sie den Referenztyp als Schlüssel in einer Tabelle hat verwenden möchten, sollten Sie auch die GetHashCode-Methode überschreiben, so dass Objekte, die ‚gleich‘ sind den gleichen Hash-Code zu erzeugen.

Eine Hash-Tabelle speichert Objekte durch den Hash-Berechnung der GetHashCode-Methode verwenden, und alle später ‚Treffer‘ verwenden diese berechnet. Sie können dies tun, indem Sie den Wert von GetHasshCode auf jedem der Eigenschaften des Objekts, in Ihrem Fall jedes des Bytes im Array zurückgegeben zu stützen. Dies ist ein Beispiel dafür, wo ich es benutzen Sie können dies auch in einer IEqualityComparer die Sie in Ihrem hashtable verwenden:

 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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top