2010-02-17 50 views
11

組我有這個類如何通過自定義類型使用LINQ

public class Item 
{ 
     public Coordinate coordinate { get; set; } 
     ... 
     ... 
} 

有了座標,其定義是這樣的:

public class Coordinate 
{ 
     public Coordinate(float latitude, float longitude) 
     { 
      Latitude = latitude; 
      Longitude = longitude; 
     } 

     public float Latitude { get; private set; } 
     public float Longitude { get; private set; } 
} 

而且我希望有一個LINQ查詢這樣的:

var grouped = from it in items 
       group it by it.Coordinate into grp 
       select grp; 

As mentioned here by MSDN我認爲這是可能的,如果我將覆蓋座標類上的等於:

如果您必須將 查詢變量傳遞給其他方法,請使用指定類型。 使用 鍵爲 自動實現的屬性創建一個特殊類,然後重寫等於 和GetHashCode方法。您也可以使用 結構,在這種情況下,您不必 嚴格地覆蓋那些 方法。欲瞭解更多信息,請參閱如何 :實現一個不可變類 具有自動實現的屬性

的Equals實現爲協調類:

public override bool Equals(object obj) 
{ 
     var coord = obj as Coordinate; 
     if(coord == null) return false; 
     return (Latitude == coord.Latitude && Longitude == coord.Longitude); 
} 

我仍然不能得到通過類似的座標我的LINQ查詢到組作爲我失敗試驗表明:

[TestMethod] 
public void GroupBy_3ItemsWith2DifferentCoordinates_Returns2Groups() 
{ 
    var items = new List<Item> 
     { 
      new Item {Coordinate = new Coordinate(10, 10)}, 
      new Item {Coordinate = new Coordinate(10, 10)}, 
      new Item {Coordinate = new Coordinate(12, 10)}, 
     }; 
    var grouped = from it in items 
        group it by it.Coordinate into g 
        select g; 
    Assert.AreEqual(2, grouped.Count()); 
} 

有一個過載將IEqualityComparer作爲參數的GrouBy方法,但是使用group子句的等價方法是否存在? 我做錯了什麼?有什麼想法嗎?

回答

22

您已經顯示了Equals實現,但沒有顯示GetHashCode。您需要覆蓋這兩個(並以一致的方式)以使分組工作。

樣品的GetHashCode實現:

public override int GetHashCode() 
{ 
    int hash = 23; 
    hash = hash * 31 + Latitude.GetHashCode(); 
    hash = hash * 31 + Longitude.GetHashCode(); 
    return hash; 
} 

注意,對於準確平等比較float值始終是很危險的 - 但我至少希望你的單元測試通過,因爲他們沒有進行任何的計算。

+0

剛剛試了一下,這就是我失蹤。非常感謝你:) public override int GetHashCode() return {((int)Latitude * 100)^((int)Longitude * 100); } – 2010-02-17 11:39:35

+0

如果這就是你的哈希代碼正在做的事情,你應該確保你的相等代碼匹配它 - 它們應該是彼此一致的。 – 2010-02-17 11:43:06

+0

Latitude.GetHashCode()^ Longitude.GetHashCode()在反轉Latitude和Longitude時給出相同的結果。所以這不是一個好的解決方案,因爲我想確保coord(x,y)!= coord(y,x); 由於操作的順序很重要,您的代碼可以正常工作。 感謝精度,這有助於:) – 2010-02-18 08:45:44

2

存在過載到GrouBy 方法,其採用的IEqualityComparer 作爲參數,但使用組子句是那裏的 等效?

你總是可以通過匿名類型組,如果你只是想快速在線解決方案,不擔心打的鑰匙確切類型:

var grouped = 
    from it in items 
    group it by new {it.Coordinate.Latitude, it.Coordinate.Longitude}; 
+0

我知道這個解決方案,但你不會有座標類作爲關鍵,只是一個匿名類型。 – 2010-02-18 06:35:11

相關問題