Note that there are some explanatory texts on larger screens.

plurals
  1. POVB.NET linq group by with anonymous types not working as expected
    primarykey
    data
    text
    <p>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:</p> <pre><code>from n in new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable() group n by new { FirstLetter = n[0], Length = n.Length } </code></pre> <p>I added the string "Jon" to the end of the array to get an actual grouping, and came up with the following result:</p> <p><img src="https://i.stack.imgur.com/DL4qP.png" alt="C# LINQPad result"></p> <p>This was exactly what I was expecting. Then, in LINQPad, I went to the VB.NET version of the same query:</p> <pre><code>' 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 </code></pre> <p>The result does not properly group Jay/Jon together.</p> <p><img src="https://i.stack.imgur.com/GhycT.png" alt="VB.NET LINQPad result"></p> <p>After pulling my hair out for a bit, I discovered <a href="http://msdn.microsoft.com/en-us/library/bb384767.aspx" rel="nofollow noreferrer">this MSDN article</a> 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 <code>Key</code> keyword to make them immutable. So, I changed the query to this (notice the addition of <code>Key</code>):</p> <pre><code>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 </code></pre> <p>This gave me the correct result:</p> <p><img src="https://i.stack.imgur.com/QAI9t.png" alt="enter image description here"></p> <p>So my question is this:</p> <ol> <li>Why does mutability/immutability of anonymous types matter when linq does an equality comparison? Notably, in Linq-to-SQL it doesn't matter at all, which is likely just a product of the translation to SQL. But in Linq-to-objects it apparently makes all the difference.</li> <li>Why would MS have chosen to make VB's anonymous types mutable. I see no real advantage, and after mucking around with this issue I see some very real disadvantages. Namely that your linq queries can have subtle bugs.</li> </ol> <p>-- EDIT --</p> <p>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 <a href="https://stackoverflow.com/questions/6556077/distinct-in-linq-with-anonymous-types-in-vb-net">here</a> and <a href="https://stackoverflow.com/questions/626935/why-group-by-key-of-anonymous-objects-does-not-behave-the-way-expected">here</a> on stackoverflow. Here's another example of the issue using anonymous types and Distinct:</p> <pre><code>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) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload