Dot-Net
如何使用 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;正如 MSDN 在這裡提到的,我認為如果我在我的 Coordinate 類上覆蓋 Equals ,這是可能的:
如果必須將查詢變數傳遞給另一個方法,請使用命名類型。使用鍵的自動實現屬性創建一個特殊類,然後覆蓋 Equals 和 GetHashCode 方法。您還可以使用結構,在這種情況下,您不必嚴格重寫這些方法。有關更多資訊,請參閱如何:實現具有自動實現屬性的不可變類
等於 Coordinate 類的實現:
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 子句的等價物?難道我做錯了什麼??有什麼想法嗎?
您已經展示了 Equals 實現,但沒有展示 GetHashCode。您需要覆蓋兩者(並以一致的方式)才能進行分組。
範例 GetHashCode 實現:
public override int GetHashCode() { int hash = 23; hash = hash * 31 + Latitude.GetHashCode(); hash = hash * 31 + Longitude.GetHashCode(); return hash; }請注意,比較
float精確相等的值總是有些冒險 - 但我至少希望您的單元測試能夠通過,因為它們沒有執行任何計算。