I'm querying a collection using linq and grouping my data by 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 good, when use an anonymous type. 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 query accordingly
var querty = from post in ds.Appointments
group post by new YearMonth(post.DateOfVisit.Year,
post.DateOfVisit.Month);
then grouping is not working and I'm getting a plain list of the objects. Why?
As schglurps already said, you have to override GetHashCode
and Equals
, since the GroupBy
method (and others) rely on these.
The GroupBy
method creates the final groups based on the hash code (and equality) of the objects it groups on.
So for each item in your sequence, it checks if there's already a group with the same hash code, then checks if the item is equal to the key of the group. If there's no matching group, it creates a new one.
In your case, since you don't override GetHashCode
, each instance of YearMonth
will have a different hash code (collisions aside), so each item will result in a new group being created.
Just have a look at the relevant reference source.
Here's 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);
}
}
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