One of the things most people find hard to use in LINQ is GroupBy or the LINQ expression group … by (they are mostly equivalent).
When starting to use that, I was also confused, mainly because of two reasons:
- GroupBy returns a IGrouping<TKey, TElement> generic interface, but the classes that implement it are internal and not visble from outside the BCL (although you could artificially create your own).
This interface extends the IEnumerable<TElement> in a full “is a” fashion adding a Key member.
This has two consequences:- Because it is a “is a” extension of the IEnumerable<TElement>, you can use foreach to enumerate the
TElement
members for the current group inside the grouping.
No need to search for a Value that has the Elements, as the Group is the Elements. - The Key member is indeed the current instance of what you are grouping over. Which means that Count<TElement>, are for the current group in the grouping.
- Because it is a “is a” extension of the IEnumerable<TElement>, you can use foreach to enumerate the
- The LINQ expression syntax for grouping on multiple columns is not straightforward:
- Grouping on multiple columns uses a bit different syntax than you are used from SQL.
(Another difference is that SQL returns a set, but groups are IEnumerable) - You also need to be a bit careful to make sure the group keys are indeed distinct.
- Grouping on multiple columns uses a bit different syntax than you are used from SQL.
Most people don’t see the IGrouping<TKey, TElement> because they use the var keyword to implicitly the LINQ result.
Often – when using any anonymous type – var is the only way of using that result.
That is fine, but has the consequence that it hides the actual type, which – when not anonymous – is a good way of seeing what happens behind the scenes.
David Klein gave an example for the multi column grouping and also shows that if you use LINQPad, you can actually see the IGrouping<TKey, TElement> in action.
Mike Taulty skipped the Group By Syntax for Grouping on Multiple Columns in his Grouping in LINQ is weird (IGrouping is your friend). So my examples include that.
Note that I don’t cover all the LINQ group by stuff, here, for instance, I skipped the into part.
There are some nice examples on MSDN covering exactly that both using Method based and Expression based LINQ.
The examples are based on these two classes, similar to what Mike did. Read the rest of this entry »