2016-03-12 58 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