Since the creation of the .Net Framework, Microsoft has kept the
concept of “Type Safe” at the forefront of their design goals. When
1.1 shipped, the framework had a “generic” collection type called an
ArrayList that seemed to break this goal. Microsoft quickly went above
and beyond with the 2.0 framework by adding Generics and Anonymous
Methods to the mix. Anonymous methods coupled with Generics paved the
way to Lambda expressions, Extension methods, and LINQ (Language
INtegrated Query). The topic of this paper is loosely defined as: The
path to understanding Lambda and LINQ.
What came first?
Iterating through a collection with a for-each construct has been
around for a long time. .Net has the capability and in the beginning
it was the recommended way of looping through a collections of widgets
to find something or count something. The basic construct is:
private int CountForEach()
{
int count = 0;
foreach (DLDog Dog in Dogs)
{
if (Dog.FoodBrand == "Purina" )
{
count++;
}
}
return count;
}
Nothing too earth shattering about this. Assuming we have a collection
of 10 dogs and 3 of them use “Purina”, we will return a count of 3.
How would Generics and Anonymous methods change this syntax? In the
.Net 2.0 framework we can simplify the previous code a little as
follows:
private int CountGenericDelegate()
{
MyActionCount = 0;
Dogs.ForEach(MyAction);
return MyActionCount;
}
This is a little misleading because we still need to write the delegate
method “MyAction” but it does give us some flexibility in that we can
pass any method to the ForEach generic method that adheres to the
Action<T> prototype which is a predefined delegate in .Net 2.0.
Here is what the MyAction needs to look like in this example:
private void MyAction(DLDog Dog)
{
if (Dog.FoodBrand == "Purina" )
{
MyActionCount++;
}
}
Another predefined delegate is the Predicate<T> delegate. This
one returns a Boolean based on some condition. The <T> is
typically your List<T> type. Here is an example that uses the
Predicate<T>:
private List<DLDog> QueryDelegate()
{
return Dogs.FindAll(ByTypeAndCost);
}
// Predicate<T> typed method for FindAll
bool ByTypeAndCost(DLDog Dog)
{
if (Dog.DogType == "German Sheperd" && Dog.AnnualVet > 1500M)
return true;
else
return false;
}
Enter .NET 3.5 - SWEEEET!
In .NET 3.5 Microsoft pulled all punches and really exploited the
power of delegates, generics, and anonymous methods. Building on that
technology they added extension methods, lambda, and LINQ to the
system. Now our first count example can be simplified as:
private int CountLambda()
{
MyActionCount = 0;
return Dogs.Count(n => n.FoodBrand == "Purina" );
}
This syntax is foreign as you can see but after a short explanation it
will become very natural. The “=>” operator is loosely defined as
“Goes To”. Under the covers - the compiler is doing this:
private int CountLambda()
{
this.MyActionCount = 0;
return this.Dogs.Count<DLDog>(delegate(DLDog n)
{
return (n.FoodBrand == "Purina" );
});
}
Previous code sample courtesy of “Reflector“…
Lambda is nothing more than syntactic sugar for inline anonymous
methods and the .Count method on a generic list is nothing more than an
extension method provided by the .Net 3.5 framework to the .Net 2.0’s
generic list class. No smoke and mirrors here!
Now LINQ is another animal but simply exploits everything up to this point and the previous example looks like:
private int CountLinq()
{
var query = from dog in Dogs select dog;
return query.Count(n => n.FoodBrand == "Purina" );
}
The query variable is of type IEnumerable<T> and the T in this
case is a DLDog object. The compiler ends up with the following:
private int CountLinq()
{
return this.Dogs.Select<DLDog, DLDog>(
delegate(DLDog dog)
{
return dog;
}).Count<DLDog>(
delegate(DLDog n)
{
return (n.FoodBrand == "Purina" );
}
);
}
Notice the use of the .Select extension method. The method is defined as:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
(In the Visual Studio help system… )
So in summary - LINQ is really syntactic sugar for the extension methods provided by the .NET 3.5 framework! Simple!