You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Linq GroupBy对匿名与自定义类型的表现差异原因

问题根源:分组键的相等性判断逻辑差异

这个问题的核心在于匿名类型和自定义类型在Linq分组时的相等性比较规则完全不同,导致了分组结果的差异,我来给你拆解清楚:

1. 匿名类型为什么能正确分组?

C#的匿名类型有个编译器自动赋予的“隐藏福利”:它会帮你自动重写Equals()和GetHashCode()方法,而且这两个方法的判断逻辑是基于所有属性的实际值进行比较。

比如你用匿名类型作为分组键的代码:

var GroupQueryA = dt.AsEnumerable()
    .GroupBy(row => new { 
        Supplier = row["Supplier"], 
        Invoice = row["Invoice"] 
    })
    .Select(g => new {
        g.Key.Supplier,
        g.Key.Invoice,
        TotalAmount = g.Sum(row => row.Field<decimal>("Amount"))
    });

当两行数据的Supplier和Invoice值完全相同时,它们生成的匿名对象会被GroupBy判定为“相等的键”,自然会被合并到同一组,最终得到你预期的2行结果。

2. 自定义GroupKeys类型为什么分组失败?

如果你只是简单定义了一个没有重写相等性方法的自定义类型,比如:

public class GroupKeys
{
    public object Supplier { get; set; }
    public object Invoice { get; set; }
}

默认情况下,这个类型继承自Object类的Equals()和GetHashCode()方法,而这两个方法的默认逻辑是判断对象的引用是否相同,而非属性值是否一致。

也就是说,即使两个GroupKeys对象的Supplier和Invoice值完全一样,但它们是两个独立的实例(每次new GroupKeys()都会创建新对象),GroupBy就会把它们当成不同的分组键,原本应该合并的组被拆分开,最终得到3行结果。

3. 怎么修复自定义类型的分组问题?

要让自定义类型能正确分组,你需要手动重写Equals()和GetHashCode()方法,让相等性判断基于属性值而非对象引用:

public class GroupKeys : IEquatable<GroupKeys>
{
    public object Supplier { get; set; }
    public object Invoice { get; set; }

    public bool Equals(GroupKeys other)
    {
        if (other is null) return false;
        return Equals(Supplier, other.Supplier) && Equals(Invoice, other.Invoice);
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as GroupKeys);
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Supplier, Invoice);
    }
}

这样修改后,GroupBy就会根据Supplier和Invoice的属性值来判断键是否相等,分组结果就会和匿名类型的一致了。

内容的提问来源于stack exchange,提问作者Sylwester Santorowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:11:46