实现2d行的相等性

时间:2016-03-12 10:09:40

标签: c# gethashcode

我有一个简单的类定义2d行:

$ mkdir a b
$ setfacl -m u:nobody:rx a
$ setfacl -m d:u:nobody:rx b
$ diff -u <(getfacl a) <(getfacl b)
--- /dev/fd/63  2016-03-12 11:10:20.032239216 +0100
+++ /dev/fd/62  2016-03-12 11:10:20.024239117 +0100
@@ -1,9 +1,12 @@
-# file: a
+# file: b
 # owner: andrea
 # group: andrea
 user::rwx
-user:nobody:r-x
 group::rwx
-mask::rwx
 other::r-x
+default:user::rwx
+default:user:nobody:r-x
+default:group::rwx
+default:mask::rwx
+default:other::r-x

我的主要目标是使用.Distinct()从List中获取不同的行。在我的情况下,如果他们的坐标相等而不管方向,则两条线是相等的(线1,2-> 3,4等于3,4-> 1,2)。我将实现Equals,如:

public class Line {
    public double X1 { get; set; }
    public double Y1 { get; set; }
    public double X2 { get; set; }
    public double Y2 { get; set; }
}

但我不知道如何实现GetHashCode(因为我理解在使用Distinct()时必须使用它)

1 个答案:

答案 0 :(得分:2)

如果您先定义Point,然后根据2 Line定义Point,这会变得容易一些。

现在,要计算Line的可靠(但不受方向影响)哈希值,请确保在计算哈希值时一致地对点进行排序。

将所有内容整合到一个完整的实现中(其中还包含运算符==!=):

public class Point
{
    public double X { get; set; }
    public double Y { get; set; }

    protected bool Equals(Point other)
    {
        return X.Equals(other.X) && Y.Equals(other.Y);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Point) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (X.GetHashCode()*397) + Y.GetHashCode();
        }
    }

    public static bool operator ==(Point left, Point right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Point left, Point right)
    {
        return !Equals(left, right);
    }
}

public class Line
{
    public Point Point1 { get; set; }
    public Point Point2 { get; set; }

    protected bool Equals(Line other)
    {
        return Equals(Point1, other.Point1) && Equals(Point2, other.Point2) 
             || Equals(Point1, other.Point2) && Equals(Point2, other.Point1);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Line) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var orderedPoints =
                new[] {Point1, Point2}.OrderBy(p => p != null ? p.X : 0)
                                      .ThenBy(p => p != null ? p.Y : 0).ToList();
            var p1 = orderedPoints[0];
            var p2 = orderedPoints[1];
            return ((p1 != null ? p1.GetHashCode() : 0)*397) 
                   + (p2 != null ? p2.GetHashCode() : 0);
        }
    }

    public static bool operator ==(Line left, Line right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Line left, Line right)
    {
        return !Equals(left, right);
    }
}