The concept of this article is based on this short video. This article is a graph of how we reached up to LINQ, and the evolution of C# from 1.0 to 3.5. Is LINQ a new thing or just sweet syntax for old ugly code? In this article, we will look at the journey of C# up to LINQ in less than 10/15 minutes. So let's get started and demystify the LINQ.

We will need some scaffolding code. We will use a City class as follows:

This is a good enough solution. The problem with this code is “tight coupling”. C# 1.0 provided a delegate based composable solution to this problem. The following is the refactored version of this code:

As shown in step 1, we added a delegate IsParticularState. Step 2 is the target method for this delegate. Step 3 is the refactored call to the foreach loop which takes a delegate and cities collection as an input parameter. Step 4 will output the city name and state.

Notice the filter instead of the simple if condition. filter(localCity) is a delegate call. By doing this, we decoupled the filter logic into a separate method:

staticbool IsCalifornia(City c)

Still this is too much of a code for implementing a simple filter logic. Wouldn't it be nice if we don't have to add an additional filter method. Yes, that's where C# 2.0 anonymous methods will be helpful. So, the code above can be refactored as follows:

Notice the inline delegate and anonymous method. This is a C# 2.0 feature - anonymous because this method has no name.

This is a good move, but still needs a delegate code. What if we want to improve this code using C# 3.0. Instead of using anonymous methods, we can use lambda expression as follows:

PrintCityInfo(cities,ctemp=>ctemp.State=="CA");

Isn't this code elegant? From 7+ lines, a delegate and a target method call in C# 1.0 to less than half a line of code in C# 3.0. This is the power of lambda expression. Underneath, the compiler is doing all the heavy lifting for us. Lambda expression is a combination of implicit variable and anonymous methods. In our example, ctemp is an implicit variable and ctemp.State=="CA" is an anonymous method.

And now comes LINQ. What if we want to filter the end result on multiple conditions or want to sort the output based on some predefined order like city name? We can do this without LINQ. But LINQ provides an elegant solution for this as shown below:

Here we defined a new method PrintCityInfousingLINQ. This is the same as the PrintCityInfo method. Rather than taking a collection and delegate as an input parameter, PrintCityInfousingLINQ takes enumerator as an input parameter. Another important factor is generics. Generics add the type safety and provide all other well documented benefits.

Let's order the end result by city name. This is a typical order by clause in TSQL. With LINQ, this can be written as follows:

Without the orderby clause, Santa Ana will be the first result. With order by clause, Irvine will be the first record.

Conclusion

From the trivial if condition in C# 1.0 to LINQ in C# 3.0, there is a continuum of logic and syntax. Imagine writing...

from ctemp in cities
where ctemp.State=="CA"orderby ctemp.Name
select ctemp;

... using if conditions or delegates. LINQ brings the much needed improvement on the syntax front in addition to its support for SQL, XML and objects. With LINQ, intent is closely matched with the language syntax.

Update : While explaning LINQ to folks coming in from traditional procedural programming background, I used this example to explain Lambda basics. Hope this will be useful to others - please let me know - LINQPad is used to test this code