我知道LINQ可以通过利用匿名类型进行分组,所以如果我使用自己的对象进行分组,它也会分组。但是,它不是(至少在我的用法中)。
例如,使用我想要的两个参数的以下匿名类型组:
.GroupBy(v => new { v.GroupId })
但是一旦我使用自己的对象,它就不再进行分组了:
.GroupBy(v => new MyGrouping { GroupId = v.GroupId })
使用以下对象
private class MyGrouping : IMyGrouping
{
public int GroupId { get; set; }
public override bool Equals(object obj) { return Equals((MyGrouping)obj); }
public bool Equals(MyGrouping obj)
{
return this.GroupId == obj.GroupId ;
}
}
我在自己的对象中遗漏了什么,还是不支持?
正如每张海报所指出的那样,我的Equals实现存在缺陷,因此我使用Resharper推荐的等式检查对其进行了修改,只是为了与预期不同并按预期进行分组。
private class MyGrouping : IMyGrouping
{
public int GroupId { get; set; }
public override bool Equals(object obj)
{
var myGrouping = obj as MyGrouping;
return myGrouping != null ? Equals(myGrouping) : false;
}
public bool Equals(MyGrouping other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return other.GroupId == GroupId;
}
public override int GetHashCode()
{
return GroupId;
}
}
对我来说,这是一个失败者,因为我的目标是减少代码......我之前的实现是通过动态变量进行分组,所以我现在可以重新考虑这个。
答案 0 :(得分:4)
MyGrouping类肯定存在一些问题。
首先,如果调用它,则覆盖的Equals方法具有无限递归,因为您从未将对象强制转换为特定类型。其次,您不会覆盖GetHashCode()
方法(如果您覆盖Equals()
,则应始终执行此操作)。第三,如果您要为特定类型实施自定义Equals方法,则还应将IEquatable<T>
接口添加到您的班级。
我的课程看起来像:
private class MyGrouping : IMyGrouping, IEquatable<IMyGrouping>
{
public int GroupId { get; set; }
public override bool Equals(object obj)
{
if(obj == null) return false;
if(GetType() != obj.GetType()) return false;
return Equals(obj as MyGrouping);
}
public override bool GetHashCode()
{
return GroupId.GetHashCode();
}
public bool Equals(IMyGrouping obj)
{
if(obj == null) return false;
return GroupId == obj.GroupId;
}
}
答案 1 :(得分:1)
首先,你的Equals覆盖很糟糕,首先尝试使用:
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (this.GetType() != obj.GetType())
return false;
return this.GroupID == ((MyGrouping)obj).GroupId;
}