Using Extension Methods in .net 2.0

Update: I must give credit where credit is due. Daniel Moth commented on this post and pointed out that he discovered this quite a while ago. Although if I only posted completely original content, then I probably would only have one or two posts on this blog. :-)

I was at the Richmond .net users group meeting tonight and a comment was made about automatic properties and how if the project was targeting .net 3.5 then we could use them. Well, I later explained that automatic properties, along with extension methods, were just compiler tricks and since in Visual Studio 2008 even if you target the .net framework 2.0 you are still using the C# 3.0 compiler; therefore you can use these features. They don’t produce any invalid IL to the .net 2.0 runtime, so they can be used.

Well, I was 100% correct about the automatic properties, but I was only 99% correct about the extension methods. :-) You have to a do a *bit* of work to get it working, but it is a very tiny bit. So, I thought it would be a wonderful blog post, so here it goes…

When I created a .net 2.0 targeted application like this:

New 2.0 Project

And then I try to implement this horribly useless extension method:

  public static class ExtensionMethodClass
  {
    public static string ExtensionMethodTest
      (this string value, int start)
    {
      return value.Substring(start);
    }
  }

Then I get this error:

Extension Method Error

I saw this error and I said, hmmmmmm, that is in a .net 3.5. Well lets reflect that attribute anyways. When I did so I got this:

Extension Attribute Reflection

Well, that is easy enough. Lets doooooooooooooooo it!! So I just implemented my own (make sure you fake the namespace):

namespace System.Runtime.CompilerServices
{
  [AttributeUsage(AttributeTargets.Method 
    | AttributeTargets.Class 
    | AttributeTargets.Assembly)]
  public sealed class ExtensionAttribute : Attribute
  {
  }
}

Now I compile and run this:

  static void Main(string[] args)
  {
    string test = "Test String!!";
    string result = test.ExtensionMethodTest(3);
  }

And everything works great! Hopefully you can get some use from this!

Be Sociable, Share!

14 comments

  1. Hey Justin,
    I think I saw you in the back there tonight. I was the rude guy in the front row interjecting… :D You know, the one who won the Zune. Hehe.

    I’m talking with Darrell about doing a few of these talks myself pretty soon. You gonna do one?

  2. Now this is really interesting! Thanks for the tip. I haven’t checked, but I’m assuming the reason this works is because VS’08 still uses the 3.5 compiler even though you are targeting 2.0.

  3. oh, duh. You already explained it. I guess I should have read the entire post, and not just the code before I commented.

    Thanks!

  4. That is old news, but good to see more people re-discovering the same hack ;)

    Note that when you use any of the new compiler features agianst Fx 2.0, you should make sure the target machine has CLR SP1 to be completely safe.

  5. I’m sure that most of the stuff that I "discover" has already been discovered by others. :-) I see that your post is from May, so I’m less than a year behind! And with the timezones and all, you are even further ahead of me. :-)

  6. LOL… sorry, the emphasis of my comment was meant to be on the CLR v2.0 [b]SP1[/b] bit. Everybody ignores that little fact and at some point it will bite someone (there are bug fixes in the CLR SP1 to cope with some edge IL scenarios that the new compilers emit).

  7. I’ll have to go through that list of changes you have for the SP1 release. Honestly I didn’t really pay much attention to it when it came out. Thanks for the link.

  8. Great hack! Simple and effective…I love it!

  9. Just been having a play with this today and I noticed something interesting. If you have your extension methods in a seprate class library they don’t seem to work.

    I thought I’d have a crack at this for a .NET 2.0 build I’m on which is a multi-tiered application, and the extensions I’ve written are all there within the Business Logic tier, but when I go to the UI tier I can no longer access them. What a cop out :P

  10. In order to get access to the extension methods you have to include whatever namespace those extension methods happen to reside in. Are you including those namespaces?

  11. Yeah still no joy doing that, got the namespace with my Extensions static class as a reference but it didn’t help.
    Wonder if it’s a problem because where I’m trying to use it is in a different namespace… shouldn’t, but who know’s what craziness VS has to do to get it to work!

  12. Great post. I’m trying to use them but having trouble. I have something like this:

    public interface ILocation { … }

    public class Location : ILocation { … }

    public class UsrLocation : Location { … }

    public class PartnerLocation : Location { … }

    I want to append some methods to IList<ILocation> using extensions (I need to use IList) like this:

    public static bool HasLocation(this IList<ILocation> locations, ILocation location) { … }

    To be able to make this calls:

    ILocation location1 = new Location();
    IList<Location> locations1 = new List<Location>();
    bool a1 = locations1.HasLocation(location1);

    ILocation location2 = new UsrLocation();
    IList<UsrLocation> locations2 = new List<UsrLocation>();
    bool a2 = locations2.HasLocation(location2);

    ILocation location3 = new PartnerLocation();
    IList<PartnerLocation> locations3 = new List<PartnerLocation>();
    bool a3 = locations3.HasLocation(location3);

    But I get compile errors. Any ideas? Thanks in advance.

  13. @yorch What version of Visual Studio are you using? You need to be using VS2008 for this to work.

  14. Thanks Justin! I’m using VS2008 but targeting to net-2.0 for server restrictions.
    I have make it work (kind of) making this change:

    public static bool HasLocation<T>(this IList<T> locations, ILocation location) where T : ILocation { … }

    So I need to use:

    ILocation location1 = new Location();
    IList<Location> locations1 = new List<Location>();
    bool a1 = locations1.HasLocation<Location>(location1);

    I have not yet been able to find a way for just using: locations1.HasLocation(location1)

Leave a comment