Latest Replies
Thursday
Jan102008

How to use .NET 3.5 syntax and compiler features for .NET 2.0?

UPDATE: there is an updated version of this article.


I've just squeezed out a couple of hours to install and try Visual Studio 2008 today. There were two surprises that came with that:

  • Unpleasant - Resharper does not fully support .NET 3.5 (it almost hurts). It is planned to have R# 4.0 release around 2008 Q1.

  • Pleasant - Some .NET 3.5 compiler and syntax sugar features work with .NET 2.0.

Let me expand on the last item. These .NET 3.5 features work with .NET 2.0:

  • local variable inference

  • anonymous types

  • object initializers

  • extensions methods

  • query expressions

  • lambda expressions

In other words, this code does compile in Visual Studio 2008 when .NET 2.0 framework is targeted:

public static class Program
{
  static void Main(string[] args)
  {
    List<Customer> customers = new List<Customer> 
    { 
      new Customer{Name="Bob", Age=23}, 
      new Customer{Name="Donald",Age=10}
    };

    var query = from c in customers
                where c.Age &gt; 11
                select c.Name;

    query.Print();
  }

  public static void Print<T>(this IEnumerable<T> collection)
  {
    foreach (T item in collection)
    {
      Console.WriteLine(item);
    }
  }
}

public class Customer
{
  public string Name { get; set; }
  public int Age { get; set; }
}

To make this happen you just need to add the following namespace and class declarations:

namespace System
{
  public delegate TRes Func<TSrc, TRes>(TSrc src);
}
namespace System.Runtime.CompilerServices
{
  public class ExtensionAttribute : Attribute { }
}

namespace System.Linq
{
  public static class Enumerable
  {
    public static IEnumerable<TSrc> Where<TSrc>(
      this IEnumerable<TSrc> source, Func<TSrc, bool> predicate)
    {
      List<TSrc> res = new List<TSrc>();
      foreach (TSrc s in source)
      {
        if (predicate(s))
        {
          res.Add(s);
        }
      }

      return res;
    }
    public static IEnumerable<TRes> Select<TSrc, TRes>(
      this IEnumerable<TSrc> source, Func<TSrc, TRes> selector)
    {
      List<TRes> res = new List<TRes>();
      foreach (TSrc s in source)
      {
        TRes t = selector(s);
        res.Add(t);
      }

      return res;
    }
  }
}

And if you remove the code above (i.e.: using C# preprocessor directive #if), and switch then target framework to .NET 3.5, the program will still compile.

It is sweet, is not it?

If this works as it is expected I'd be glad to have those features in .NET 2.0 projects. This will help to produce more efficient code.

Update: In the next post I'll explain how to compile autofac project (it extensively uses lamda expressions and extensions) against .NET 2.0. And there'll be some compatibility code in a single file.

Update: alternatively you can use LinqBridge library to compile against .NET 2.0 or simply manually reference System.Core.dll (open source helper project Lokad Shared Libraries has this done).

« One more interesting and fresh .NET IoC container: autofac | Main | Common development principles for xLim »

Reader Comments (4)

[...] to compile all the mentioned code to target .NET 2.0 (as all the code from my code snippets compiles into). However, in this case I was not able to use the LinqBridge library since it does not have support [...]

[...] http://rabdullin.com/how-to-use-net-35-syntax-and-compiler-features-for-net-20/ © 2008 Scott Hanselman. All rights reserved. [...]

the System.Core.dll from compact framework 3.5 is usable from 2.0 full framework projects - makes all classes from system.linq available

September 29, 2008 | Unregistered Commentercristian

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>