我正在使用
linq查询集合,并使用以下代码通过datetime属性对数据进行分组:
- var querty = from post in ds.Appointments
- group post by new
- {
- Year = post.DateOfVisit.Year,Month = post.DateOfVisit.Month
- };
当使用匿名类型时,一切都很好.但是,如果我定义自己的类
- 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);
- }
- }
- var querty = from post in ds.Appointments
- group post by new YearMonth(post.DateOfVisit.Year,post.DateOfVisit.Month);
然后分组不起作用,我得到一个简单的对象列表.为什么?
解决方法
正如schglurps已经说过的那样,你必须覆盖GetHashCode和Equals,因为GroupBy方法(以及其他方法)依赖于这些.
GroupBy方法基于它所分组的对象的哈希码(和相等)来创建最终组.
因此,对于序列中的每个项目,它会检查是否已有一个具有相同哈希码的组,然后检查该项是否等于该组的键.如果没有匹配的组,则会创建一个新组.
在您的情况下,由于您不重写GetHashCode,因此YearMonth的每个实例都将具有不同的哈希代码(冲突旁边),因此每个项目将导致创建一个新组.
只需看看相关的reference source.
这是一个示例实现:
- public class YearMonth : IEquatable<YearMonth>
- {
- public readonly int Year;
- public readonly int Month;
- public YearMonth(int 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);
- }
- }