VB.NET linq group с анонимными типами не работает должным образом - PullRequest
11 голосов
/ 14 июля 2011

Я играл с некоторыми образцами linq, поставляемыми с LINQPad.В папке «C # 3.0 в двух словах» в главе 9 «Группировка» приведен пример запроса под названием «Группировка по нескольким ключам».Он содержит следующий запрос:

from n in new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable()
group n by new
{
    FirstLetter = n[0],
    Length = n.Length
}

Я добавил строку «Jon» в конец массива для получения фактической группировки и получил следующий результат:

C# LINQPad result

Это было именно то, что я ожидал.Затем в 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.

VB.NET LINQPad result

Немного потянув за волосы, я обнаружил эту статью MSDN , в которой обсуждаются анонимные типы 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

Это дало мне правильный результат:

enter image description here

Итаку меня такой вопрос:

  1. Почему изменчивость / неизменность анонимных типов имеет значение, когда linq выполняет сравнение на равенство?Примечательно, что в Linq-to-SQL это вообще не имеет значения, что, вероятно, является просто продуктом перевода в SQL.Но в Linq-to-objects это, по-видимому, имеет все значение.
  2. Почему MS решила сделать изменяемые анонимные типы VB.Я не вижу никакого реального преимущества, и после осмотра этой проблемы я вижу некоторые очень реальные недостатки.А именно, что ваши запросы linq могут иметь незначительные ошибки.

- EDIT -

Просто интересная дополнительная часть информации ... По-видимому, эта проблема ключевого свойства широко известна.Я просто не знал, для чего Google.Это обсуждалось здесь и здесь в стеке потока.Вот еще один пример проблемы с использованием анонимных типов и 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)

1 Ответ

11 голосов
/ 14 июля 2011

Модификатор Key влияет не только на изменчивость, но и на поведение Equals и GetHashCode.Только Key свойства включены в эти вычисления ... что явно влияет на группировку и т. Д.

Что касается того, почему это отличается для VB - я не знаю.Мне это тоже кажется странным.Я знаю Я рад, что C # работает так же, как и :) :) Даже если можно утверждать, что создание свойств , необязательно изменяемых, имеет смысл, я не понимаю, почему это должнопо умолчанию.

...