I'm trying to do a Linq GroupBy on some objects using an explicit key type. I'm not passing an IEqualityComparer
to the GroupBy, so according to the docs:
The default equality comparer
Default
is used to compare keys.
It explains the EqualityComparer<T>.Default
property like this:
The
Default
property checks whether typeT
implements theSystem.IEquatable<T>
generic interface and if so returns anEqualityComparer<T>
that uses that implementation.
In the code below, I'm grouping an array of Fred
objects. They have a key type called FredKey
, which implements IEquatable<FredKey>
.
That should be enough to make the grouping work, but the grouping is not working. In the last line below I should have 2 groups, but I don't, I just have 3 groups containing the 3 input items.
Why is the grouping not working?
class Fred
{
public string A;
public string B;
public FredKey Key
{
get { return new FredKey() { A = this.A }; }
}
}
class FredKey : IEquatable<FredKey>
{
public string A;
public bool Equals(FredKey other)
{
return A == other.A;
}
}
class Program
{
static void Main(string[] args)
{
var f = new Fred[]
{
new Fred {A = "hello", B = "frog"},
new Fred {A = "jim", B = "jog"},
new Fred {A = "hello", B = "bog"},
};
var groups = f.GroupBy(x => x.Key);
Debug.Assert(groups.Count() == 2); // <--- fails
}
}
From MSDN
If you implement IEquatable, you should also override the base class implementations of Object::Equals(Object) and GetHashCode() so that their behavior is consistent with that of the IEquatable::Equals method. If you do override Object::Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. This ensures that all invocations of the Equals() method return consistent results.
add this to FredKey and it should work
public override int GetHashCode()
{
return A.GetHashCode();
}