请考虑以下代码:
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));
为什么这个断言失败了?作为基本类型的数组不应该使用对象引用,是吗?那么为什么它会返回假?我可以做些什么来使这个哈希表工作吗?
答案 0 :(得分:7)
作为基本类型的数组不应该使用对象引用,是吗?
是的,应该。数组是引用类型。
一切都按照预期的方式运作。
如果您想要不同的行为,可以为数组实现比较器,比较内容并将其传递给哈希表。
答案 1 :(得分: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;
}
}
}
如果在哈希表中放置数千个数组,则应该使用更强的哈希。请查看this post以获取示例。
答案 2 :(得分: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());
答案 3 :(得分: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;
}