LINQ Farm Seeds are short posts, designed to be read in a few minutes. This one covers enumerating the operators used in LINQ to Objects. The source code for this project is available in the LINQ Farm on Code Gallery.

The LINQ to Objects operators are implemented as extension methods on the Enumerator class. The following simple LINQ query gives you a fairly clean listing of those operators:

var query = from m in typeof(Enumerable).GetMethods()
   orderby m.Name
   where m.DeclaringType == typeof(Enumerable)
   group m by m.Name into g
   orderby g.Count()
   select new { Operator = g.Key, OverloadCount = g.Count() };   
   Console.WriteLine("Approximate operator count: {0}", query.Count());
   foreach (var q in query)
   {
     Console.WriteLine(q);
   }

The output from this query looks something like this:

Approximate operator count: 50
{ Operator = All, OverloadCount = 1 }
{ Operator = AsEnumerable, OverloadCount = 1 }
{ Operator = Cast, OverloadCount = 1 }
\\ Code omitted here
{ Operator = GroupBy, OverloadCount = 8 }
{ Operator = Average, OverloadCount = 20 }
{ Operator = Sum, OverloadCount = 20 }
{ Operator = Max, OverloadCount = 22 }
{ Operator = Min, OverloadCount = 22 }

This query uses LINQ to Reflection, a feature that is built into C# 3.0. It allows you to write link queries against the code in your program.

The query begins by asking for all the methods found in the type Enumerable:

   from m in typeof(Enumerable).GetMethods()

The next line orders these methods by name:

   orderby m.Name

The data is filtered so reveal only the methods declared in this class, and not any that are inherited. This ensures that we don't see methods inherited from class object such as Equals, GetHashCode, GetType and ToString. All that is left are the extensions methods declared in this class to be used in LINQ to Objects:

   where m.DeclaringType == typeof(Enumerable)

Many of these methods are overloaded. For instance, the Min method is overloaded 22 times. Our listing would be very long if we included them all. So we group them by name to ensure that only one instance of each method is included:

   group m by m.Name into g

We order them again, this time by count:

   orderby g.Count()

By ordering them twice we first ensure that they are ordered by the number of times they are overloaded, and by their alphabetical position.

The end result is a listing of all the LINQ to Objects query operators, ordered first by count, and then alphabetically:

Name Overloads
All 1
AsEnumerable 1
Cast 1
Concat 1
ElementAt 1
ElementAtOrDefault 1
Empty 1
OfType 1
Range 1
Repeat 1
Reverse 1
Skip 1
Take 1
ToArray 1
ToList 1
Any 2
Contains 2
Count 2
DefaultIfEmpty 2
Distinct 2
Except 2
First 2
FirstOrDefault 2
GroupJoin 2
Intersect 2
Join 2
Last 2
LastOrDefault 2
LongCount 2
OrderBy 2
OrderByDescending 2
Select 2
SequenceEqual 2
Single 2
SingleOrDefault 2
SkipWhile 2
TakeWhile 2
ThenBy 2
ThenByDescending 2
Union 2
Where 2
Aggregate 3
SelectMany 4
ToDictionary 4
ToLookup 4
GroupBy 8
Average 20
Sum 20
Max 22
Min 22

 

If you would like to see the actual declaration for this class, type it once into the Visual Studio editor, then select it and press F12. You can also right click on it, and choose "Go to definition."

I want to get my hands dirty; show me more LINQ Farm posts!

kick it on DotNetKicks.com