为什么即使值相同,哈希表中的值比较也会返回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并进行比较相反的值(我强烈建议你使用字典。)
- 如何使用json动态成员获得WCF DataContract
- 为什么Entity Framework无法在LINQ语句中使用ToString()?
- Global.asax中DbContext的静态字段与控制器类中DbContext的实例字段的静态字段?
- Thread.CurrentPrincipal.Identity vs HttpContext.User.Identity
- c#编译器是否会执行多个隐式转换以从一种类型转换到另一种类型?
- 在Visual Studio中关闭表单后调试不会停止
- 从List 到IEnumerable 返回List 的转换无效,为什么?
- 请解释C#属性如何工作?
- 使用简单注入器的每线程和每Web请求的混合生活方式