3

我有一本字典,其中键是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> prevPnts = new Dictionary<XYZ, bool>();
prevPnts[new XYZ(1,1,1)] = true;

// Always says the pnt doesnt exist?
if (prevPnts.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> prevPnts = new Dictionary<XYZ, bool>(new XYZEqualityComparer());
4

3 回答 3

11

提供你自己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> prevPnts = new Dictionary<XYZ, bool>(new XYZEqualityComparer());

注意:我的实现GetHashCode只是示例性的。阅读覆盖 System.Object.GetHashCode 的最佳算法是什么?以获得更好的选择。

于 2014-01-20T22:10:44.620 回答
1

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

在这种情况下,您基本上不能将此类本身用作字典中的键,除非您IEqualityComparer<XYZ>为此类定义了实现。看看@Konrad Kokosa 的这个答案

于 2014-01-20T22:09:32.307 回答
0

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

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

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
}
于 2014-01-20T22:12:24.920 回答