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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With