实现二维线的平等

Implementing equality for 2d lines

我有简单的 class 定义二维线:

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

我的主要目标是使用 .Distinct() 从 List 中获取不同的行。在我的例子中,如果两条线的坐标无论方向如何都相等,则两条线相等(第 1,2 -> 3,4 行等于 3,4 -> 1,2)。我要实现等于:

public override bool Equals(object obj) {
    if (obj as Line == null) { return false; }
    var second = (Line)obj;
    if (this.X1 != second.X1 && this.X1 != second.X2) { return false; }
    if (this.Y1 != second.Y1 && this.Y1 != second.Y2) { return false; }
    if (this.X2 != second.X2 && this.X2 != second.X1) { return false; }
    if (this.Y2 != second.Y2 && this.Y2 != second.Y1) { return false; }
    return true;
}

但我不知道如何实现 GetHashCode(据我所知,在使用 Distinct() 的情况下有必要实现它)

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

现在,要计算 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);
    }
}