如何定义基于双键分组的IGrouping类型
问题解决方法
方案一:使用具名类替代匿名类型(推荐)
匿名类型无法作为公开属性的泛型参数,所以你需要定义一个具名类作为分组键,并且必须重写Equals和GetHashCode方法(或实现IEquatable<T>),否则GroupBy无法正确识别相同的分组条件。
- 定义
AccountInfo类并实现相等性判断:
public class AccountInfo : IEquatable<AccountInfo> { public string Id { get; } public string Name { get; } public AccountInfo(string id, string name) { Id = id; Name = name; } // 基于属性值判断对象相等 public bool Equals(AccountInfo other) { if (other is null) return false; return Id == other.Id && Name == other.Name; } // 基于属性值生成哈希码 public override int GetHashCode() { return HashCode.Combine(Id, Name); } // 重写父类Equals方法,调用强类型判断逻辑 public override bool Equals(object obj) { return Equals(obj as AccountInfo); } }
- 修改属性的泛型参数:
public List<IGrouping<AccountInfo, License>> LicensesInfo { get; set; }
- 执行分组并赋值:
LicensesInfo = licenses.GroupBy(x => new AccountInfo(x.Id, x.Name)).ToList();
方案二:使用ValueTuple(C# 7.0+)
如果不想自定义类,可以用ValueTuple作为分组键,它默认实现了基于属性值的相等性判断:
- 修改属性定义:
public List<IGrouping<(string Id, string Name), License>> LicensesInfo { get; set; }
- 分组时直接使用ValueTuple:
LicensesInfo = licenses.GroupBy(x => (x.Id, x.Name)).ToList();
为什么之前用AccountInfo分组没生效?
默认情况下,Equals和GetHashCode是基于对象引用判断相等的——即使两个AccountInfo的Id和Name完全一致,它们也是不同的对象实例,GroupBy会把它们当成不同的分组键。必须重写这两个方法,让相等性判断基于属性值而非引用。
内容的提问来源于stack exchange,提问作者Quest
相关产品推荐
相关产品推荐

