As already mentioned, you must override GetHashCode and Equals , since the GroupBy (and others) method relies on them.
The GroupBy method creates GroupBy groups based on the hash code (and equality) of the objects into which it is grouped.
So, for each element in your sequence, it checks to see if there is already a group with the same hash code, and then checks if the element is equal to the group key. If there is no corresponding group, it creates a new one.
In your case, since you do not override GetHashCode , each instance of YearMonth will have a different hash code (collisions to the side), so each element will lead to the creation of a new group.
Just check out the appropriate help source .
Here is an example implementation:
public class YearMonth : IEquatable<YearMonth> { public readonly int Year; public readonly int Month; public YearMonth(int year, int month) { Year = year; Month = month; } public override string ToString() { return string.Format("{0}-{1}", Year, Month); } public bool Equals(YearMonth other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Month == other.Month && Year == other.Year; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; return Equals((YearMonth)obj); } public override int GetHashCode() { unchecked { return (Month * 397) ^ Year; } } public static bool operator ==(YearMonth left, YearMonth right) { return Equals(left, right); } public static bool operator !=(YearMonth left, YearMonth right) { return !Equals(left, right); } }
sloth source share