匿名类型的VB.NET linq分组依据无法正常工作 [英] VB.NET linq group by with anonymous types not working as expected
问题描述
我正在玩弄LINQPad附带的一些linq样本.在Chater 9-分组下的坚果壳中的C#3.0"文件夹中,有一个名为通过多个键分组"的示例查询.它包含以下查询:
I was toying around with some of the linq samples that come with LINQPad. In the "C# 3.0 in a Nutshell" folder, under Chater 9 - Grouping, there is a sample query called "Grouping by Multiple Keys". It contains the following query:
from n in new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable()
group n by new
{
FirstLetter = n[0],
Length = n.Length
}
我将字符串"Jon"添加到数组的末尾以进行实际分组,并得出以下结果:
I added the string "Jon" to the end of the array to get an actual grouping, and came up with the following result:
这正是我所期望的.然后,在LINQPad中,我转到了同一查询的VB.NET版本:
This was exactly what I was expecting. Then, in LINQPad, I went to the VB.NET version of the same query:
' Manually added "Jon"
from n in new string() { "Tom", "Dick", "Harry", "Mary", "Jay", "Jon" }.AsQueryable() _
group by ng = new with _
{ _
.FirstLetter = n(0), _
.Length = n.Length _
} into group
结果不能正确地将Jay/Jon分组在一起.
The result does not properly group Jay/Jon together.
梳理一下头发后,我发现了这篇MSDN文章讨论VB.NET匿名类型.在VB.NET中,默认情况下它们是可变的,而C#是不可变的.在VB中,您需要添加Key
关键字以使其不可变.因此,我将查询更改为此(注意添加了Key
):
After pulling my hair out for a bit, I discovered this MSDN article discussing VB.NET anonymous types. In VB.NET they are mutable by default as opposed to C# where they are immutable. In VB, you need to add the Key
keyword to make them immutable. So, I changed the query to this (notice the addition of Key
):
from n in new string() { "Tom", "Dick", "Harry", "Mary", "Jay", "Jon" }.AsQueryable() _
group by ng = new with _
{ _
Key .FirstLetter = n(0), _
Key .Length = n.Length _
} into group
这给了我正确的结果:
所以我的问题是这个
- 当linq进行相等比较时,为什么匿名类型的可变性/不可变性很重要?值得注意的是,在Linq-to-SQL中根本没有关系,这很可能只是SQL转换的产物.但是,在Linq-to-objects中,显然一切都不同.
- 为什么MS会选择使VB的匿名类型可变.我看不出任何真正的优势,并且在解决了这个问题之后,我看到了一些非常现实的劣势.也就是说,您的linq查询可能存在细微的错误.
-编辑-
只是一条有趣的额外信息...显然,这是关键财产问题,是众所周知的.我只是不知道Google要做什么.已在此处和此处.这是使用匿名类型和Distinct的问题的另一个示例:
Just an interesting extra piece of info... Apparently this is keyed property issue is widely known. I just didn't know what to Google for. It's been discussed here and here on stackoverflow. Here's another example of the issue using anonymous types and Distinct:
Dim items = New String() {"a", "b", "b", "c", "c", "c"}
Dim result = items.Select(Function(x) New With {.MyValue = x}).Distinct()
Dim result2 = items.Select(Function(x) New With {Key .MyValue = x}).Distinct()
'Debug.Assert(result.Count() = 3) ' Nope... it's 6!
Debug.Assert(result2.Count() = 3)
推荐答案
Key
修饰符不仅会影响可变性,还会影响Equals
和GetHashCode
的行为.这些计算中仅包含Key
属性...这显然会影响分组等.
The Key
modifier doesn't just affect mutability - it also affects the behaviour of Equals
and GetHashCode
. Only Key
properties are included in those calculations... which clearly affects grouping etc.
关于VB为何与众不同的原因-我不知道.我也觉得很奇怪.我知道我很高兴 C#的工作方式是这样的:)即使可以说使属性可选可变也是有意义的,但我不明白为什么它应该是默认值.
As for why it's different for VB - I don't know. It seems odd to me too. I know I'm glad that C# works the way it does though :) Even if it could be argued that making properties optionally mutable makes sense, I don't see why it should be the default.
这篇关于匿名类型的VB.NET linq分组依据无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!