字典说密钥不存在

Posted

技术标签:

【中文标题】字典说密钥不存在【英文标题】:Dictionary Says Key Doesn't Exist When It Does 【发布时间】:2014-02-10 06:44:02 【问题描述】:

我有一个字典,其中键是 XYZ 对象,值是 boolean。 XYZ 类来自 Autodesks API,所以它不是我创建的类。我正在尝试检查字典中是否存在键。

我的问题:如果字典包含键 new XYZ(1,1,1) 并且我使用 myDictionary.ContainsKey(new XYZ(1,1,1) 检查字典是否包含此键总是返回 false。

为什么会发生这种情况,我该如何解决?我认为XYZ 类需要实现其Equals 方法,但正如我之前提到的,我没有创建这个类,它是Autodesks API 的一部分。还是我做错了什么?

Dictionary<XYZ, bool> pre***ts = new Dictionary<XYZ, bool>();
pre***ts[new XYZ(1,1,1)] = true;

// Always says the pnt doesnt exist?
if (pre***ts.ContainsKey(new XYZ(1,1,1)))
   TaskDialog.Show("Contains");
else TaskDialog.Show("NOT Contains");

使用 Konrads 答案的解决方案

class XYZEqualityComparer : IEqualityComparer<XYZ>

    public bool Equals(XYZ a, XYZ b)
    
        if (Math.Abs(a.DistanceTo(b)) <= 0.05)
            return true;

        return false;
    


    public int GetHashCode(XYZ x)
    
        int hash = 17;
        hash = hash * 23 + x.X.GetHashCode();
        hash = hash * 23 + x.Y.GetHashCode();
        hash = hash * 23 + x.Z.GetHashCode();
        return hash;
    


Dictionary<XYZ, bool> pre***ts = new Dictionary<XYZ, bool>(new XYZEqualityComparer());

【问题讨论】:

【参考方案1】:

将你自己的IEqualityComparer 提供给字典,因为它不知道如何比较XYZ 类(严格来说,它通过引用比较它们):

class XYZEqualityComparer : IEqualityComparer<XYZ>

    public bool Equals(XYZ a, XYZ b)
    
        return a.X == b.X && a.Y == b.Y && a.Z == b.Z;            
        

    public int GetHashCode(XYZ x)
    
        int hash = x.X ^ x.Y ^ x.Z;
        return hash .GetHashCode();
    

然后:

Dictionary<XYZ, bool> pre***ts = new Dictionary<XYZ, bool>(new XYZEqualityComparer());

注意:我对@9​​87654326@ 的实现只是示例性的。阅读What is the best algorithm for an overridden System.Object.GetHashCode? 以获得更好的选择。

【讨论】:

【参考方案2】:

对于不覆盖EqualsGetHashCode 方法的类,比较算法将默认为引用相等而不是值相等。因此,尽管类实例的值字段/属性的值可能相同,但实例本身不同,因此相等性失败。

在这种情况下,您基本上不能将此类本身用作字典中的键,除非您为此类定义了IEqualityComparer&lt;XYZ&gt; 实现。看看this answer by @Konrad Kokosa

【讨论】:

是的,我在答案中指出了这一点。 是的,我知道。感谢您的来信。【参考方案3】:

正如您正确观察到的,如果 XYZ 类没有实现 EqualsGetHashCode 方法,那么它将进行引用比较(仅当它们引用堆上的相同对象时才如此)。

由于您无权访问该类,因此解决此问题的一个方法是将其包装在您自己的类中,您可以在其中编写一个使用 XYZ 的内容进行适当比较的 Equals 方法。

class WrapperXYZ

    XYZ xyz;

    public override bool Equals(object other)
    
        if(other is typeof(XYZ))
        
            // check the contents
        
        else
        
            return false;
        
    

    // TODO: write a hash method if you are using a dictionary

【讨论】:

您可以简单地编写一个IEqualityComparer,而不是只包装类型以覆盖EqualsGetHashCode,它设计 用于定义其他类型的相等性.

以上是关于字典说密钥不存在的主要内容,如果未能解决你的问题,请参考以下文章

如果字典键不可用,则返回 None

多值字典?

寻找一种优雅的方法来检查字典中是不是存在密钥[重复]

密钥集不存在怎样解决?

即使键存在,Python dict.get(k) 也不返回

测试一个键是不是存在于字典中,如果 [重复] 则在相同的情况下进行另一个测试