在使用匿名类型时,我在C#和VB.net中遇到了GroupBy结果的差异。特别是,当任何键都是可空类型且未设置任何值时,VB.net似乎无法正确分组项目。
说我有以下模型和一些数据:
public class Record
{
public int? RecordTypeId { get; set; }
public int? PlayerId { get; set; }
public int? TeamId { get; set; }
public int? Salary { get; set; }
}
public static class SomeRecords
{
public static List<Record> Records{ get; set; } = new List<Record>()
{
new Record() {PlayerId = 1, Salary = 100},
new Record() {PlayerId = 2, Salary = 200},
new Record() {PlayerId = 3, Salary = 300},
new Record() {PlayerId = 4, Salary = 400}
};
}
c#输出分组给了我4个键,这是我期望的,因为没有任何项的PlayerId值重叠,并且它们的TeamId或RecordTypeId都没有设置值。
var cSharpGrouping = SomeCollection.SomeRecords.GroupBy(x => new
{
RecordTypeId = x.RecordTypeId.GetValueOrDefault(),
PlayerId = x.PlayerId.GetValueOrDefault(),
TeamId = x.TeamId.GetValueOrDefault()
});
VB.net GroupBy只给我一把钥匙。
Dim vbGrouping = SomeCollection.SomeRecords.GroupBy(Function(x) New With { Key _
.RecordTypeId = x.RecordTypeId.GetValueOrDefault(), _
.PlayerId = x.PlayerId.GetValueOrDefault(), _
.TeamID = x.TeamId.GetValueOrDefault() _
})
但是,如果我将VB.net GroupBy更改为以下内容,并将密钥组合为一个字符串化密钥,则它可以按预期工作,并且我得到4个密钥:
Dim stringifiedKeysGrouping = SomeCollection.SomeRecords.GroupBy(Function(x) _
x.RecordTypeId.GetValueOrDefault().ToString() + "-" _
+ x.PlayerId.GetValueOrDefault().ToString() + "-" _
+ x.TeamId.GetValueOrDefault().ToString()
)
这到底是怎么回事?我做了一些研究,发现由于向后兼容的原因,VB.net的可为空的类型与c#的类型并不完全相同,但是由于我正在调用GetValueOrDefault,所以我不明白在这里它会如何发挥作用。
答案 0 :(得分:3)
在Visual Basic中,当且仅当两个匿名类型实例是同一类型(请参见下文)并且它们的Key
属性都相等时,两个匿名类型实例才相等。如果未定义Key
属性,则两个看似相同的实例将比较不相等。
从documentation中以粗体显示我的位置:
关键属性与非关键属性在几个基本方面不同:
仅比较键属性的值以确定两个实例是否相等。
键属性的值是只读的,不能更改。
编译器生成的用于匿名类型的哈希码算法中仅包含关键属性值。
然后继续:
只有匿名类型的实例是相同匿名类型的实例时,它们才能相等。如果满足以下条件,则编译器会将两个实例视为相同类型的实例:
它们在同一程序集中声明。
它们的属性具有相同的名称,相同的推断类型,并且以相同的顺序声明。名称比较不区分大小写。
每个属性都标记为关键属性。
每个声明中至少有一个属性是关键属性。
GroupBy
使用该类型的默认相等比较器。对于匿名类型,它调用编译器生成器Equals
方法(如上所述),该方法仅比较Key
属性。在第一个示例中,您仅定义了一个Key
属性。集合中的每个项目都具有相同的RecordTypeId
(已合并为Nothing
的{{1}})。这意味着每个匿名对象都具有相同的单个0
属性,并且每个属性都具有相同的值,因此可以进行单个分组。
解决方案是使所有属性归为Key
组中的属性(而不仅仅是第一个属性):
Key