Linq не группируется в VB.Net

В образовательных целях я попытался преобразовать следующее выражение Linq из книги "Linq in action" в VB.net

Оригинал С#

var list = 
  from book in SampleData.Books
  group book by new { book.Publisher.Name, book.Subject }
    into grouping
  select new {
    Publisher = grouping.Key.Publisher,
    Subject = grouping.Key.Subject,
    Book = grouping
  };

Моя попытка:

Dim list = _books.GroupBy(Function(book) New With {.Publisher = book.Publisher.Name,
                                                    book.Subject}).
                  Select(Function(grouping) New With {.Publisher = grouping.Key.Publisher,
                                                      .Subject = grouping.Key.Subject,
                                                      .Books = grouping})

For Each item In list
  Console.WriteLine("Publisher:" & item.Publisher & ", Subject:" & item.Subject)
  For Each Book In item.Books
    Console.WriteLine("  " & Book.Title)
  Next
Next

Это приводит к следующему выводу:

Publisher:FunBooks, Subject:Fun  
  Funny Stories  
Publisher:Joe Publishing, Subject:Work  
  LINQ rules  
Publisher:Joe Publishing, Subject:Work  
  C# on rails  
Publisher:Joe Publishing, Subject:Fun  
  All your base are belong to us  
Publisher:FunBooks, Subject:Fun  
  Bonjour mon Amour  

Я ожидал, что книги "Правила LINQ" и "С# на рельсах" сгруппированы, а также книги "Забавные истории" и "Bonjour mon Amour", потому что они имеют один и тот же Publisher и Subject. Мой анонимный ключ состоит из нового объекта из двух простых строк.

Я уже пытался искать в SO, но другие (или) ответы не решают мою проблему, Даже некоторые переводчики кода, такие как telerik или carlosag не помогают в этом случае.

Ответ 1

В этом проблема:

GroupBy(Function(book) New With {.Publisher = book.Publisher.Name,
                                  book.Subject})

Это не эквивалентно версии С#, поскольку, к сожалению, VB по умолчанию использует изменчивые свойства в анонимных типах, а изменчивые свойства не рассматриваются как часть хеш-кода или операций равенства. Вам необходимо создать оба свойства свойств "Ключ":

GroupBy(Function(book) New With {Key .Publisher = book.Publisher.Name,
                                 Key book.Subject})

Тогда он должен работать нормально. Вы можете больше узнать об анонимных типах в VB в MSDN.

Ответ 2

Пока я приветствую ваши усилия по переводу образцов, на самом деле у нас есть все образцы для LINQ in Action в С# и VB, доступные для загрузки с сайта Manning: http://www.manning.com/marguerie/. Кроме того, мы добавили образцы к образцам LinqPad, чтобы было проще попробовать образцы и сохранить ваши изменения. См. http://www.thinqlinq.com/Default/LINQ-In-Action-Samples-available-in-LINQPad.aspx для получения инструкций по доступу к нему.

Кажется, что вы работаете на примере 5.06b. Немного обновив наш перевод VB:

Dim query = _
  From book In SampleData.Books _
  Group book.Title By book.Publisher, book.Subject Into grouping = Group _
  Select _
    Publisher = Publisher.Name, _
    Subject = Subject.Name, _
    Titles = grouping 

Если вы хотите использовать синтаксис Lambda, вам нужно указать Key, как указано @johnskeet:

Dim list = SampleData.Books.GroupBy(Function(book) New With { 
                          Key .Publisher = book.Publisher.Name, 
                          Key .Subject = book.Subject}). 
               Select(Function(grouping) New With {
                  .Publisher = grouping.Key.Publisher, 
                  .Subject = grouping.Key.Subject, 
                  .Books = grouping})