It is possible to benefit from some of the .NET 3.5 features and new syntactic sugar in C# 3.0, while still targeting customers that have only .NET 2.0 Framework. That’s because these two versions share the same .NET CLR and mainly differ in the set of libraries available and compiler being used.

Features that you can leverage, while targeting .NET 2.0 Framework:

  • local variable inference;
  • anonymous types;
  • object initializers;
  • extension methods;
  • query expressions (LINQ syntax);
  • lambda expressions;
  • LINQ for objects;
  • new C# compiler that produces better code.

I’ve done this for production scenarios with ASP.NET Forms and Windows.Forms and everything has been working fine. It is possible that things like WCF or Linq2DB might also be supported, but I’ve never given it a try.

Below you will find different options for doing this in your solutions.

Note, that in any scenario you still need Visual Studio 2008 to develop these solutions.

Referencing LinqBridge

  1. Create new project targeting .NET 2.0 Framework in Visual Studio 2008. This will already give you new syntax capabilities of C# 3.0 
  2. Download LinqBridge
  3. Reference it in the project to get support for the extension methods and LINQ extensions.

Referencing System.Core

  1. Create new .NET 2.0 project just like in the previous section.
  2. Right-click on the project in Solution Explorer and select “Unload Project”
  3. Right-click on the project again again and select “Edit [ProjectName]”. You should see XML document now.
  4. Find the references section that could look like this:
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    
  5. Manually append reference to System.Core.dll:
    <Reference Include="System.Core">
      <Private>True</Private>
    </Reference>
    
  6. Save.
  7. Right-click on the project in Solution Explorer again and select “Reload”

Congratulations. You can now use some .NET 3.5 features in your project, while still having a .NET 2.0 requirement.

Implementing features yourself

That’s how ReSharper team has done it.

  1. Create .NET 2.0 project in Visual Studio 2008 to get new C# syntax sugar available.
  2. Add the snippet below to get support for extension methods:
    namespace System.Runtime.CompilerServices
    {
      public sealed class ExtensionAttribute : Attribute { }
    }
    
  3. Add the code below to get support for Where and Select Linq statements and keep on adding other features as needed.

Note, that you are basically reimplementing System.Core or LinqBridge yourself here.

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;
    }
  }
}

Remarks

  1. If you develop a solution with multiple projects, you just need to make sure that the final executable is compiled towards .NET 2.0.
  2. Solutions compiled for .NET 2.0 can run on a system with .NET 3.5 without any problems.
  3. You can also use System.Core implementation from the Mono or Microsoft Compact Framework (thanks to Cristian for pointing the CF out).