为什么即使值相同,哈希表中的值比较也会返回false?

在下面的代码中,我试图检查两个字符串是否是字谜。 为此,我计算哈希表中两个字符串中的字符,方法是将唯一字符作为键存储,并将其作为值存储在字符串中。 最后,当我去检查每个字符是否具有相同的计数时,我得到一个错误的输出,看到代码中标记为“问题”的行。 但是当我将该行中的值转换为字符串时,代码工作正常。 我错过了什么?

static bool AreAnagrams(string input1, string input2) { Hashtable uniqueChars1 = new Hashtable(); Hashtable uniqueChars2 = new Hashtable(); // Go through first string and create a hash table of characters AddToHashTable(input1, ref uniqueChars1); // Go through second string and create a second hash table of characters AddToHashTable(input2, ref uniqueChars2); // For each unique character, if the count from both hash tables are the same, they are anagrams if (uniqueChars1.Keys.Count != uniqueChars2.Keys.Count) { return false; } else { foreach (object key in uniqueChars1.Keys) { if (uniqueChars1[key] != uniqueChars2[key]) // ***PROBLEM HERE*** { return false; } } } return true; } static void AddToHashTable(string input, ref Hashtable uniqueChars) { foreach (char c in input) { if (!uniqueChars.ContainsKey(c)) { uniqueChars.Add(c, 1); } else { int charCount = Convert.ToInt32(uniqueChars[c]); charCount++; uniqueChars[c] = charCount; } } } 

Hashtable类不是通用的; 它只包含Object ,而不是特定类型。

当你这样做:

 if (uniqueChars1[key] != uniqueChars2[key]) 

uniqueChars[key]的编译时类型是Object ,而不是Int32 。 所以你正在使用不等式运算符的Object实现,它只是比较引用。 由于Int32是一个值类型,并且索引器返回一个对象,因此该值被加框 ; 并且由于您正在装箱两个值,因此您将获得两个不同的对象实例,因此引用相等性始终返回false。

你有几个选择:

  • 使用Dictionary ,这是Hashtable的通用等价物
  • 在比较之前将值转换为int

     if ((int)uniqueChars1[key] != (int)uniqueChars2[key]) 
  • 使用Equals方法比较值:

     if (!uniqueChars1[key].Equals(uniqueChars2[key])) 

除非您仍在使用.NET 1.x,否则我强烈建议您尽可能使用通用集合。 它们更安全,更直观,并且对于价值类型具有更好的性能。


附注 (与您的问题无关):您不需要通过引用AddToHashTable传递Hashtable ; 如果没有ref修饰符,代码将以完全相同的方式工作,因为Hashtable是一个引用类型,所以它始终是一个传递的引用。 只有在为uniqueChars参数指定其他内容时,或者如果您传递值类型并改变其状态(通常认为这是一件坏事)时, ref修饰符才有用。 我建议你阅读Jon Skeet关于值类型,引用类型和参数传递的精彩文章 。

您的问题来自于!=将比较两个对象上的引用相等性。 uniqueCharsX[key]返回一个对象内部的int,当你从两个哈希表中返回相同的int时,它们返回的框不是同一个框,因此你获得的值不正确。

要么使用强类型的Dictionary而不是哈希表,要么使用!uniqueChars1[key].Equals(uniqueChars2[key])而不是uniqueChars1[key] != uniqueChars2[key]将unbox int并进行比较相反的值(我强烈建议你使用字典。)