C# Extension methods

Scott Hanselman has a post about a user who doesn’t get what is cool about Ruby.

In the post you can find the below example that compares Java and Ruby in terms of code readability.

The Java code:

new Date(new Date().getTime() - 20 * 60 * 1000)

The Ruby code:

20.minutes.ago

The article was interesting but what really caught my attention was some comments from C# programmers who showed how, in a few lines of code, you can mimic the Ruby syntax in C# using extension methods.

The new version of C#, shipped with the Orcas release of Visual Studio, has a new feature called extension methods. Extension methods were added to the .Net languages to support LINQ and they provide a way to attach methods to classes without changing their code.

The below code is copied and modified from the comments of Ian Cooper in the aforementioned blog post.

public static class TimeExtensions {

  public static TimeSpan Minutes(this int numberOfMinutes) {
    return new TimeSpan(0, numberOfMinutes, 0);
  }

  public static DateTime Ago(this TimeSpan numberOfMinutes) {
    return DateTime.Now.Subtract(numberOfMinutes);
  }
}

In the above code we defined a class, called TimeExtensions, which contains two extension methods. Notice the this keyword on the left of the fist parameter (both methods take one parameter in the example code) of the methods. The this keyword tells the C# compiler that a method is an extension method. The parameter annotated with the this keyword is the object on which the extension method is called. If I am correct, the methods are not really added to the classes (you can’t find them via reflection), the compiler at-compile-time translates them into static method calls.

In our example the first method, called Minutes, will be added to the int class (probably via auto-boxing) and the second method, called Ago, will be added to the TimeSpan class.

Now, to use the extension methods that we defined above we have to import them using the using TimeExtensions statement. This is a really good thing since the usage of extension methods is always explicit. You have to import them to use them and if you don’t want to use them you don’t import them.

using System;
using TimeExtensions;

public class HelloWorld {
  public static void Main() {
    Console.WriteLine( 20.Minutes().Ago() );
  }
}

20.Minutes().Ago() is pretty close to 20.minutes.ago :-)

For a nice tutorial about C# 3.0 extension methods see: New “Orcas” Language Feature: Extension Methods.