Home > Enterprise >  Using LINQ, can I give the "grouping" a name in VB.NET like I can in C#?
Using LINQ, can I give the "grouping" a name in VB.NET like I can in C#?

Time:04-12

My goal is to group and transform data, but have both the transformed and un-transformed "grouped data" available.

Consider the following minimal C# example:

var data = new[] { ("a", 1), ("a", 2), ("b", 1) };

var groupedAndTransformed =
    from d in data
    group d by d.Item1 into g
    select new
    {
        Untransformed = g,
        Transformed = g.Key   string.Join(",", g.Select(tuple => tuple.Item2))
    };

Now I try to do the same in VB.NET, but I can only achieve that with a two-step process, because VB.NET's Group By works somewhat differently than C#'s group by:

Dim data = {("a", 1), ("a", 2), ("b", 1)}

Dim step1 =
    From d In data
    Group d By d.Item1 Into Group

Dim groupedAndTransformed =
    From g In step1
    Select
        Untransformed = g,
        Transformed = g.Item1   String.Join(",", g.Group.Select(Function(tuple) tuple.Item2))

The problem seems to be that VB.NET's Group By puts the result of the grouping into some kind of "global namespace": If I continue writing LINQ code directly after Group d By d.Item1 Into Group, I have both Item1 and Group in scope. However, I don't have a name for the IGrouping consisting of them (dubbed g in C#), so I need the second step.

Can I somehow tell VB's Group By statement to give me a name for the IGrouping? The only other workarounds I found were to use (a) functional syntax instead of declarative LINQ syntax (i.e., call Enumerable.GroupBy directly) or (b) nest step1 into the second step (i.e., From g In (...step1...)). Is there something I have missed?

CodePudding user response:

It's too bad that the C# and VB LINQ syntax is so incompatible. I think the following VB LINQ is as close as you can get the to the original (with Option Infer On of course):

Dim data = { ("a", 1), ("a", 2), ("b", 1) }

Dim groupedAndTransformed = From d In data
    Group d By d.Item1 Into g = Group
    Select New With {
        Key .Untransformed = g,
        Key .Transformed = Item1 & String.Join(",", g.Select(Function(tuple) tuple.Item2))
    }

I've tested and it compiles and runs but it's hard to tell if it will function identically.

CodePudding user response:

What Dave said, but I just wanted to note that overall it might be neater to use method syntax:


    Dim groupedAndTransformed = data.GroupBy(
        Function(d) d.Item1,
        Function(k, g) New With {
            Key .Untransformed = g
            Key .Transformed = g.Select(Function(tuple) tuple.Item2)
        }
    )

Or if you want to dump the Untransformed, there's an overload that will help reduce the subselect


    Dim groupedAndTransformed = data.GroupBy(
        Function(d) d.Item1,
        Function(d) d.Item2,
        Function(k, g) New With {
            Key .Transformed = k & String.Join(",", g)
        }
    )

I do wish they'd shorten Function to F

  • Related