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

时间:2015-01-11 00:52:34

标签: c# hashtable

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

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

2 个答案:

答案 0 :(得分:5)

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

执行此操作时:

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

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

您有几种选择:

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

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

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

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


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

答案 1 :(得分:1)

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

要么使用强类型Dictionary<char, int>而不是哈希表,要么使用!uniqueChars1[key].Equals(uniqueChars2[key])而不是uniqueChars1[key] != uniqueChars2[key],这将取消对int进行解包并在值上进行比较(我强烈建议您使用词典。)