我正在玩弄LINQPad附带的一些linq样本。在“Nutshell中的C#3.0”文件夹中,在Chater 9 - Grouping下,有一个名为“按多个键分组”的示例查询。它包含以下查询:
from n in new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable()
group n by new
{
FirstLetter = n[0],
Length = n.Length
}
我将字符串“Jon”添加到数组末尾以获得实际分组,并得出以下结果:
这正是我所期待的。然后,在LINQPad中,我转到了相同查询的VB.NET版本:
' 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组合在一起。
在我的头发拉了一下后,我发现this MSDN article讨论了VB.NET匿名类型。在VB.NET中,默认情况下它们是可变的,而不是C#,它们是不可变的。在VB中,您需要添加Key
关键字以使其不可变。所以,我将查询更改为此(请注意添加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
这给了我正确的结果:
所以我的问题是:
- 编辑 -
只是一个有趣的额外信息...显然这是关键的财产问题是众所周知的。我只是不知道谷歌要做什么。在stackoverflow上讨论了here和here。这是使用匿名类型和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)
答案 0 :(得分:11)
Key
修饰符不仅会影响可变性,还会影响Equals
和GetHashCode
的行为。这些计算中只包含Key
个属性...这显然会影响分组等。
至于为什么它与VB不同 - 我不知道。这对我来说似乎很奇怪。我知道我很高兴C#的工作方式尽管如此:)即使有人认为使可选 mutable属性有意义,我也不明白为什么它应该是默认值。