C# 3.0 for mere mortals, part 1: Extension methods

Pick a .NET class, any class. Take a class from the .NET Framework. Is there any method that you think is missing from that class?

Let's say you picked the ArrayList. Too bad it does not have a Concat method, that will take the ToString() of every object in the ArrayList and concatenate it to one big string. The sample code below shows just that. 

ArrayList list = new ArrayList();
list.Add(42);
list.Add("The answer to everything");
string all = list.Concat(';');
Console.WriteLine(all);

Well, with extension methods you can create this method anyway. Remember, Concat is NOT a member of the original ArrayList implementation. You can extend the class with extra methods.

In order to get the Concat method into the ArrayList class (or any method into a certain class) we will need to create a class as a carrier for the extension methods. This class can have any name you like, but it must be declared static. We'll call it ExtensionMethods. Every extension method is a regular static method, with one exception: it has a special first parameter. This first parameter is of the type which needs to be extended AND it has the this keyword defined before the type.

In our case we need a Concat method hooked up to the ArrayList. This bit of code will do that:

public namespace OurExtension
{

  public
static class
ExtensionMethods
  {
    public static string Concat(this ArrayList list, char
separator)
    {
      // Do the concatenation thingy
      return
concatenatedString();
    }
  }
}

Again, notice the three ingredients of the extension method: static class, static method, first parameter of method is of type to extended and has this before it.

Now we can use the ArrayList class and it will have a magical extra instance (!) method called Concat. There's nothing much we need to do to make that work, except importing the namespace OurExtension.

using OurExtensions;
...
ArrayList list = new ArrayList
();
string big = list.Concat(';');

There are some rules that apply to these extension methods:

  • Existing instance methods of the real class take precedence over the extension method.
    This means that if the ArrayList class would have had a Concat method of the same signature itself, it would have used that instead of the extension method.
  • Inner namespace declarations take precedence over outer namespace declarations.
    So, if you import a namespace that is below/inside your own, it will be used before any namespaces that are outside of your own namespace.

Lastly, you can also use a generic static method to make that extension method appear on a whole range of classes.

public static T[] Slice(this T[] source, int index, int count)

The declaration above will appear on all array types.

Filed under: ,

Comments

# Paul Wilson said:

This looks to be a great series Alex -- so thanks very much for taking the time to give simple examples.

Thanks, Paul Wilson

zondag 26 maart 2006 23:48
# Alex Thissen said:

Thanks Paul,

Great to hear from you again. How are things going with your OR mapper?

maandag 27 maart 2006 8:25
# Paul Wilson said:

Hey Alex:

The ORMapper's doing great -- now I've got a WebPortal built on top of it and ASP.NET v2.0 (http://www.WilsonWebPortal.com).

Later, Paul

dinsdag 28 maart 2006 20:58
# Yahrii said:

Hey Alex

A really useful piece of code. Unfortunately I've got a problem with the code:

public static string Concat(this ArrayList list, char separator).

I get an error on the this keyword: "Type expected". What to do?

Thanks in advance

Yahrii

donderdag 25 mei 2006 11:25
# Yahrii said:

Never mind that. Just realized it's for C# 3.0. Looking forward to that release...

donderdag 25 mei 2006 12:14