匿名类型的VB.NET linq分组依据无法正常工作 [英] VB.NET linq group by with anonymous types not working as expected

查看:78
本文介绍了匿名类型的VB.NET linq分组依据无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩弄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

这给了我正确的结果:

所以我的问题是这个

  1. 当linq进行相等比较时,为什么匿名类型的可变性/不可变性很重要?值得注意的是,在Linq-to-SQL中根本没有关系,这很可能只是SQL转换的产物.但是,在Linq-to-objects中,显然一切都不同.
  2. 为什么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修饰符不仅会影响可变性,还会影响EqualsGetHashCode的行为.这些计算中仅包含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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆