自定义类作为 C# 中字典的键不起作用

Custom Class as key for Dictionary in C# not working

提问人:Sanju 提问时间:6/21/2022 最后编辑:M. JustinSanju 更新时间:11/15/2023 访问量:250

问:

我最近开始学习 C#,但被困在这个特殊案例上。是的,我已经解决了前面的问题,但无法了解我的代码中的问题是什么。自定义类在字典中用作键,但找不到键这是我能找到的最接近的一个,但这里给出的答案似乎对我不起作用。

我有一个字典注册表<Customers,字符串>。 Customers 是一个具有 2 个字符串的类:s1 和 s2。客户可以匹配 s1 或 s2(两者都不是必需的)。

类客户:

public class Customers
    {
        public string _s1;
        public string _s2;

        public Customers(string s1, string s2)
        {
            _s1 = s1;
            _s2 = s2;
        }

        public class EqualityComparer : IEqualityComparer<Customers>
        {
            public bool Equals(Customers x, Customers y)
            {
                Console.WriteLine("Inside Equals");
                return ((x._s1.Equals(y._s1)) || (x._s2.Equals(y._s2)));
            }
            public int GetHashCode(Customers x)
            {
                return x._s1.GetHashCode() ^ x._s2.GetHashCode();
            }
        }
    }

程序.cs:

Dictionary<Customers, string> registry = new Dictionary<Customers, string>(new Customers.EqualityComparer());

Customers key = new Customers("1", "2");
Customers key2 = new Customers("12", "21");
registry.Add(key, "12");
registry.Add(key2, "22");
Customers lookUp1 = new Customers("1", "2");
Customers lookUp2 = new Customers("1", "32");
if (registry.ContainsKey(lookUp2))
{
    Console.WriteLine("Found");
}
else
{
    Console.WriteLine("Not Found");
}

问题是,当 s1 和 s2 都匹配时,我会得到“找到”,但是当只有一个匹配时,我会得到“未找到”,尽管相应地更改了 Equals() 并在构造函数中给出了新 EqualityComparer 的引用。

此外,对于 lookup1,我确实得到了“Inside Equals”,但不是 lookup2,我不确定为什么。

C# 字典 哈希 相等

评论


答:

2赞 Guru Stron 6/21/2022 #1

发生这种情况是因为基本上是一个哈希表Dictionary

使用其键检索值的速度非常快,接近 O(1),因为该类是作为哈希表实现的。Dictionary<TKey,TValue>

匹配的第一条规则是哈希码应该相等,并且 (for ) 肯定与 (for ) 不同。"1".GetHashCode() ^ "2".GetHashCode()key"1".GetHashCode() ^ "32".GetHashCode()lookUp2

评论

0赞 Sanju 6/21/2022
谢谢!这似乎确实是问题所在。我更改了返回x._s1。GetHashCode() ^ x._s2。GetHashCode();返回 0,它似乎有效。但是我读到这可能会导致代码效率不那么高?
0赞 Guru Stron 6/21/2022
@Sanju我想不出从头顶支持“或”逻辑的实现。我建议只使用简单,多个键引用相同的值。GetHashcodeDictionary<string, string>
1赞 Dmitry Bychenko 6/21/2022
问题更深层次:即使我们把 - 糟糕但正确的实现,字典也无法正常工作。基本的相等设计不正确。public int GetHashCode(Customers x) => 0;
0赞 Guru Stron 6/21/2022
@DmitryBychenko是的,代码/方法存在多个问题。
10赞 Dmitry Bychenko 6/21/2022 #2

您在相等设计方面有问题。每个相等对应必须遵循以下规则:

  1. A.Equals(A) == true对于所有人.A
  2. 如果那么对于所有人.A.Equals(B) == trueB.Equals(A) == trueA, B
  3. 如果那么对于所有人.A.Equals(B) && B.Equals(C) == trueA.Equals(C) == trueA, B, C

正如我们所看到的,规则 #3(传递规则)被打破了

   Customer A = new Customer("x", "y");
   Customer B = new Customer("x", "z");
   Customer C = new Customer("p", "z");

由于相等性实现不正确,因此无法正常工作Dictionary<K, V>