LINQ Group使用匿名类型比它应该更好地工作

时间:2013-08-21 07:45:36

标签: c# linq

假设我有一个定义为:

的类
public class DataHolder
{
    public string PropA { get; set; }
    public string PropB { get; set; }
    public string PropC { get; set; }
    public int PropD { get; set; }
}

并且有一个DataHolder数组的实例声明为:

    var x=new DataHolder[]{
        new DataHolder(){PropA="A",PropB="X",PropC="J",PropD=1},
        new DataHolder(){PropA="A",PropB="Y",PropC="J",PropD=3},
        new DataHolder(){PropA="A",PropB="Y",PropC="J",PropD=5},
        new DataHolder(){PropA="B",PropB="X",PropC="K",PropD=7},
        new DataHolder(){PropA="B",PropB="Y",PropC="L",PropD=9},
        new DataHolder(){PropA="C",PropB="X",PropC="J",PropD=11},
        new DataHolder(){PropA="C",PropB="X",PropC="J",PropD=13},
        new DataHolder(){PropA="C",PropB="Y",PropC="J",PropD=15},
        new DataHolder(){PropA="C",PropB="Z",PropC="J",PropD=17}
    };

我运行LINQ GroupBy查询,如下所示:

    var t = x.GroupBy(c => new { A = c.PropA, B = c.PropB, C = c.PropC })

当我检查结果时,我发现t有7个元素,这是数组中不同的PropA,PropB,PropC组合的数量,这是我想要的效果(是的!)。 但后来我想,它实际上不应该起作用,因为匿名类型的每个新实例应该与其他实例不相等,并且应该有9个元素。为什么它按照我的第一个想法运行应该?

2 个答案:

答案 0 :(得分:7)

因为匿名类型:

  

因为匿名类型上的Equals和GetHashCode方法是根据属性的Equals和GetHashcode方法定义的,所以同一匿名类型的两个实例只有在它们的所有属性相等时才相等。

(摘自MSDN

所以他们有一个超载的Equals,这使得一个“理智的”逐个财产比较。

答案 1 :(得分:6)

请注意,如果满足以下两个条件,则两个匿名类型“相等”:

1)他们是相同的类型

MSDN:“如果程序集中的两个或多个匿名对象初始值设定项指定了相同顺序的属性序列,并且具有相同的名称和类型,则编译器将对象视为相同类型的实例。它们共享相同的编译器生成的类型信息。“)

2)他们所有的属性都是平等的。

请注意,“相同的顺序”在这里很重要:

var a = new {A = 1, B = "Dog"};
var b = new {A = 1, B = "Dog"};
var c = new {B = "Dog", A = 1};

a.Equals(b) // true
a.Equals(c) // false -- a and c are instances of different types.