字典说密钥不存在
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());
注意:我对@987654326@ 的实现只是示例性的。阅读What is the best algorithm for an overridden System.Object.GetHashCode? 以获得更好的选择。
【讨论】:
【参考方案2】:对于不覆盖Equals
和GetHashCode
方法的类,比较算法将默认为引用相等而不是值相等。因此,尽管类实例的值字段/属性的值可能相同,但实例本身不同,因此相等性失败。
在这种情况下,您基本上不能将此类本身用作字典中的键,除非您为此类定义了IEqualityComparer<XYZ>
实现。看看this answer by @Konrad Kokosa
【讨论】:
是的,我在答案中指出了这一点。 是的,我知道。感谢您的来信。【参考方案3】:正如您正确观察到的,如果 XYZ 类没有实现 Equals
和 GetHashCode
方法,那么它将进行引用比较(仅当它们引用堆上的相同对象时才如此)。
由于您无权访问该类,因此解决此问题的一个方法是将其包装在您自己的类中,您可以在其中编写一个使用 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
,而不是只包装类型以覆盖Equals
和GetHashCode
,它设计 用于定义其他类型的相等性.以上是关于字典说密钥不存在的主要内容,如果未能解决你的问题,请参考以下文章