How to group by custom types with linq

.net, group-by, linq

Solution

You've shown the Equals implementation, but not GetHashCode. You need to override both (and in a consistent way) for grouping to work.

Sample GetHashCode implementation:

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

Note that comparing `float` values for exact equality is always somewhat risky - but I'd at least expect your unit tests to pass, given that they're not performing any calculations.

Problem

I have this class ``` public class Item { public Coordinate coordinate { get; set; } ... ... } ``` With Coordinate being define like this: ``` 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; } } ``` And I want to have a linq query like that : ``` var grouped = from it in items group it by it.Coordinate into grp select grp; ``` As mentioned here by MSDN I thought this was possible if I would override Equals on my Coordinate class : Use a named type if you must pass the query variable to another method. Create a special class using auto-implemented properties for the keys, and then override the Equals and GetHashCode methods. You can also use a struct, in which case you do not strictly have to override those methods. For more information see How to: Implement an Immutable Class That Has Auto-Implemented Properties Equals implementation for Coordinate class : ``` public override bool Equals(object obj) { var coord = obj as Coordinate; if(coord == null) return false; return (Latitude == coord.Latitude && Longitude == coord.Longitude); } ``` still I cant get my linq query to group by similar coordinates, as my failing test shows : ``` [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()); } ``` There is an overload to the GrouBy method that takes an IEqualityComparer as a parameter, but is there the equivalent using the group clause? Am I doing something wrong?? Any thoughts?

Original source