GroupBy匿名类型差异-VB.net与C#
当使用匿名类型时,我在C#和VB.net中遇到了GroupBy结果的差异。特别是,当任何键都是可空类型且未设置值时,VB.net似乎无法正确分组项 假设我有以下模型和一些数据:GroupBy匿名类型差异-VB.net与C#,c#,vb.net,linq,grouping,anonymous-types,C#,Vb.net,Linq,Grouping,Anonymous Types,当使用匿名类型时,我在C#和VB.net中遇到了GroupBy结果的差异。特别是,当任何键都是可空类型且未设置值时,VB.net似乎无法正确分组项 假设我有以下模型和一些数据: 公共类记录 { 公共int?RecordTypeId{get;set;} public int?PlayerId{get;set;} public int?TeamId{get;set;} public int?Salary{get;set;} } 公共静态类记录 { 公共静态列表记录{get;set;}=new Lis
公共类记录
{
公共int?RecordTypeId{get;set;}
public int?PlayerId{get;set;}
public int?TeamId{get;set;}
public int?Salary{get;set;}
}
公共静态类记录
{
公共静态列表记录{get;set;}=new List()
{
新记录(){PlayerId=1,Salary=100},
新记录(){PlayerId=2,Salary=200},
新记录(){PlayerId=3,Salary=300},
新记录(){PlayerId=4,Salary=400}
};
}
c#output分组给了我4个键,这是我所期望的,因为PlayerId没有重叠的值,而且它们都没有为TeamId或RecordTypeId设置值
var csharpgrouting=SomeCollection.SomeRecords.GroupBy(x=>new)
{
RecordTypeId=x.RecordTypeId.GetValueOrDefault(),
PlayerId=x.PlayerId.GetValuerDefault(),
TeamId=x.TeamId.GetValueOrDefault()
});
VB.net GroupBy只给我一个键
Dim vbGrouping=SomeCollection.SomeRecords.GroupBy(函数(x)使用{键新建_
.RecordTypeId=x.RecordTypeId.GetValueOrDefault(),\u
.PlayerId=x.PlayerId.GetValuerDefault()_
.TeamID=x.TeamID.GetValueOrDefault()_
})
但是,如果我将VB.net GroupBy更改为以下内容,并将这些键组合成一个字符串化键,它将按预期工作,我将得到4个键:
Dim stringifiedKeysGrouping=SomeCollection.SomeRecords.GroupBy(函数(x)\u
x、 RecordTypeId.GetValueOrDefault().ToString()+“-”_
+x.PlayerId.GetValueOrDefault().ToString()+“-”_
+x.TeamId.GetValueOrDefault().ToString()
)
这到底是怎么回事?我做了一些研究,了解到由于向后兼容性的原因,VB.net的可空类型与c#的不完全相同,但是我不明白这在这里是如何起作用的,因为我调用了GetValuerDefault 在Visual Basic中,两个匿名类型实例是相等的,当且仅当它们是相同的类型(请参见下文)并且它们的
Key
属性都相等时。如果未定义键
属性,则两个看似相同的实例将进行不相等的比较
从我的,大胆的:
键属性与非键属性在几个基本方面有所不同:
- 仅比较键属性的值,以确定两个实例是否相等。
- 键属性的值是只读的,不能更改
- 对于匿名类型,编译器生成的哈希代码算法中只包含键属性值
- 它们在同一程序集中声明
- 它们的属性具有相同的名称、相同的推断类型,并且以相同的顺序声明。名称比较不区分大小写
- 每个中相同的属性被标记为关键属性。
- 每个声明中至少有一个属性是键属性
GroupBy
使用该类型的默认相等比较器。对于匿名类型,它调用编译器生成器Equals
方法,该方法(如上所述)仅比较键
属性。在第一个示例中,您只定义了一个键
属性。集合中的每个项目都具有相同的RecordTypeId
(无
,您已合并到0
)。这意味着每个匿名对象都有相同的键
属性,所有属性都具有相同的值,因此只有一个分组
解决方案是将分组中的所有属性设置为Key
属性(而不仅仅是第一个):
在Visual Basic中,两个匿名类型实例当且仅当它们是相同类型(请参见下文)且它们的
Key
属性都相等时才相等。如果未定义键
属性,则两个看似相同的实例将进行不相等的比较
从我的,大胆的:
键属性与非键属性在几个基本方面有所不同:
- 仅比较键属性的值,以确定两个实例是否相等。
- 键属性的值是只读的,不能更改
- 对于匿名类型,编译器生成的哈希代码算法中只包含键属性值
- 它们在同一程序集中声明
- 它们的属性具有相同的名称、相同的推断类型,并且以相同的顺序声明。名称比较不区分大小写
- 每个中相同的属性被标记为关键属性。
- 每个声明中至少有一个属性是键属性
GroupBy
使用该类型的默认相等比较器。对于匿名类型
Dim vbGrouping = SomeCollection.SomeRecords.GroupBy(Function(x) New With { _
Key .RecordTypeId = x.RecordTypeId.GetValueOrDefault(), _
Key .PlayerId = x.PlayerId.GetValueOrDefault(), _
Key .TeamID = x.TeamId.GetValueOrDefault() _
})