Introduction

Language INtegrated Query in C# 3.0 is pure joy to use. Once you try it, you don't want to stop.

But a few of us, for whatever reason, are still using Visual Studio 2005. In my case, I didn't want to pay $550 for the upgrade to VS2008 Pro, but I didn't want to lose features like Macros and Code Diagrams by switching to Visual C# Express Edition or SharpDevelop. So, I came up with a way I could use LINQ-to-Objects in C# 2.0.

Note: If you are stuck with .NET Framework 2.0, but you are using C# 3.0 or Visual Studio 2008, you don't need the code in this article. Just use LinqBridge.

Using the Code

Here is some simple C# 3.0 LINQ code. This code contains a query and several calls to extension methods in the System.Linq.Enumerable class. Of course, since they are extension methods, the code doesn't actually mention Enumerable.

Look at the first WriteLine statement: instead of words.Take(3).ToArray(), it reads Linq(words).Take(3).ToArray(). Linq() is a helper function that simply wraps an IEnumerable object in a PoorMansLinq object; it could have been written new PoorMansLinq<string>(words).Take(3).ToArray() instead.

PoorMansLinq provides most of the LINQ functionality such as Where(), OrderBy(), etc. It forwards all the calls to the static class Enumerable. PoorMansLinq does not include all the functionality of Enumerable:

It does not include static methods such as Empty() and Range(first, last) that are not extension methods.

It doesn't include AsEnumerable(), which makes no sense without the extension methods feature.

It cannot include specializations for specific kinds of T, such as Average<double>() and Sum<int>(), because as far as I know, there is no way to do it with Generics in C# 2.0. Therefore, in order to compute the Sum, Average, Min, or Max of integers, doubles, or decimals, you need to call the method in Enumerable directly.

PoorMansLinq also includes Sorted(), which is a shortcut for OrderBy(x => x) that you see in the second WriteLine statement. In C# 2.0, you would have to write OrderBy(delegate(string x) { return x; }), which is cumbersome.

As I mentioned, you can't Sum numbers using the Linq(numbers).Sum() syntax, so the third WriteLine uses Enumerable.Sum(numbers) instead.

The forth WriteLine demonstrates how a simple query is translated:

from x in numbers
where x > 300
select x

becomes:

Linq(numbers)
.Where(delegate(int x) { return x > 300; })

I omitted the Select clause, which is not needed in this case. Here's how it looks with the redundant Select clause:

Share

About the Author

Since I started programming when I was 11, I wrote the SNES emulator "SNEqr", the FastNav mapping component, and LLLPG, among other things. Now I'm old.

In my spare time I'm developing a system called Loyc (Language of your choice), which will include an enhanced C# compiler. Many programs have an add-in architecture; why not your programming language? I'm also looking for a life partner. Oh hi future wife! Wazzap.