Linq没有在VB.Net中分组

Mar*_*kus 10 linq c#-to-vb.net

出于教育目的,我尝试将以下Linq表达式从"Linq in action"转换为VB.net

原创C#

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
  };
Run Code Online (Sandbox Code Playgroud)

我的尝试:

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
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

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  
Run Code Online (Sandbox Code Playgroud)

我预计,"LINQ规则"和"C#on rails"这些书籍以及书籍"Funny Stories"和"Bonjour mon Amour"都会被分组,因为它们具有相同的发布者和主题.我的匿名密钥包含两个简单字符串的新对象.

我已经尝试在SO中搜索,但其他()答案并没有解决我的问题.在这种情况下,甚至像telerikcarlosag这样的代码翻译也没有帮助.

Jon*_*eet 7

这就是问题:

GroupBy(Function(book) New With {.Publisher = book.Publisher.Name,
                                  book.Subject})
Run Code Online (Sandbox Code Playgroud)

这不等同于C#版本,因为不幸的是,默认情况下VB 在匿名类型中使用可变属性,并且可变属性不被视为哈希代码或相等操作的一部分.您需要将两个属性设为"Key"属性:

GroupBy(Function(book) New With {Key .Publisher = book.Publisher.Name,
                                 Key book.Subject})
Run Code Online (Sandbox Code Playgroud)

那它应该工作正常.您可以在MSDN上阅读有关VB中匿名类型的更多信息.


Jim*_*ley 5

虽然我对您翻译样本的努力表示赞赏,但我们实际上已经从Manning网站下载了所有C#和VB中的LINQ in Action示例: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 
Run Code Online (Sandbox Code Playgroud)

如果要使用Lambda语法,则需要将键指定为@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}) 
Run Code Online (Sandbox Code Playgroud)