2016-03-12 60 views
1

实现平等我有简单的类定义2D线:二维线

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

我的主要目标是让从列表中使用.Distinct()不同线路。在我的情况下,如果两个线的坐标相等而不论方向如何(线1,2 - > 3,4等于3,4 - > 1,2),则两线相等。我要实现equals,如:

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的(因为我知道这是必要的,使其在使用的情况下,鲜明的())

+0

也许你可以使用的IEqualityComparer? http://stackoverflow.com/questions/13331985/how-do-i-use-a-custom-comparer-with-the-linq-distinct-method – Gusman

+1

[C#中的GetHashCode指引](http:// stackoverflow.com/questions/462451/gethashcode-guidelines-in-c-sharp) –

+0

如果你一直使它返回0,它会工作,但性能会成问题。时间复杂度将等于'O(n)'。你可以让散列码通过一些公式传递参数,并返回结果。它将大大提高性能。例如'返回X1 + X2 + Y1 + Y2'。或者您可以考虑订单,例如'X1 + X2 << 1 + Y1 << 2 + Y2 << 3'。请注意,如果您让公式具有较少的散列冲突,则性能会更好。哈希碰撞意味着两个不同的对象返回相同的哈希码。顺便说一句,生成哈希码的算法也影响性能 –

回答

2

这变得更容易,如果一点您首先定义一个Point,然后根据2 Point s定义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); 
    } 
} 
+0

感谢您的详细解答! – user1820686

+0

我改变了GetHashCode实现的细节,使用'+'而不是'*',否则0坐标会搞乱计算。 – spender