Using strong types in linq grouping request

I query the collection using linq and group my data using the datetime property using the following code:

 var querty = from post in ds.Appointments group post by new { Year = post.DateOfVisit.Year, Month = post.DateOfVisit.Month }; 

Everything is fine when an anonymous type is used. But if I define my own class

 class YearMonth { public int Year; public string Month; public YearMonth(int year, int month) { Year = year; Month = month; } public override string ToString() { return string.Format("{0}-{1}",Year,Month); } } 

and modify my request accordingly.

 var querty = from post in ds.Appointments group post by new YearMonth(post.DateOfVisit.Year, post.DateOfVisit.Month); 

then grouping does not work and I get a simple list of objects. Why?

+6
source share
1 answer

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); } } 
+6
source

All Articles