Extension Methods

[Blog Map]  [Table of Contents]  [Next Topic]

This blog is inactive.
New blog: EricWhite.com/blog

Blog TOCNote: This article is a topic in a much larger tutorial on writing pure functional code in C#.  Extension methods are only one of the pieces in a much larger puzzle.  Functional programming in C# allows us to write shorter programs that perform better, and are much more robust.  Query Composition using Functional Programming Techniques explains extension methods in their proper context.

Extension methods are special methods that, while they are not part of a data type, you can call them as though they were part of the data type.  Extension methods are a feature of C# 3.0.

Writing Extension Methods

To write an extension method, you do the following:

·         Define a public static class.

·         Define a public static method in the class where the first argument is the data type for which you want the extension method.

·         Use the this keyword on the first argument to your public static method. The this keyword denotes the method as an extension method.

This special syntax is actually simply a natural extension of what you do normally when you want to make a utility method for a class that you don't want to (or can't) extend.  A common pattern when you want to write a utility method is to define a static method that takes an instance of the class as the first parameter.  This is exactly what an extension method is - the only difference is that you can then write a call to the method as though it were part of the class, and the compiler will find and bind to the extension method.

Note that the following class does not define a PrintIt method:

public class MyClass
{
public int IntField;
public MyClass(int arg)
{
IntField = arg;
}
}

This static class defines an extension method for the MyClass class:

public static class MyClassExtension
{
public static void PrintIt(this MyClass arg)
{
Console.WriteLine("IntField:{0}", arg.IntField);
}
}

You can now call the PrintIt method as though it were part of the class.

MyClass mc = new MyClass(10);
mc.PrintIt();

When you run this code, it outputs:

IntField:10

But the really cool thing is that you can write extension methods for a type that in and of itself, can't contain methods.  The most important example of this is that you can write extension methods for interfaces.  You could also write an extension method for an abstract class.

You can define extension methods for parameterized types as well as non-parameterized types.  The standard query operators are almost all extension methods that are defined on IEnumerable<T>.

Note that you can define your own extension methods for IEnumerable<T>.  When there isn't a standard query operator that does exactly what you want, you can write your own extension method.  This is a powerful technique that adds expressiveness to your code.

When you are writing pure functional code, extension methods are important.  There are times that writing extension methods on IEnumerable<T> is the way that you want do things.  We'll be using this technique sometimes when writing FP code.

Extension Methods are Vital for LINQ

Extension methods are an integral part of LINQ.  Consider the following code that contains a LINQ query expression:

int[] source = new[] { 3, 6, 4, 8, 9, 5, 3, 1, 7, 0 };

IEnumerable<int> query =
from i in source
where i >= 5
select i * 2;

foreach (var i in query)
Console.WriteLine(i);

This code is functionally identical to this:

int[] source = new[] { 3, 6, 4, 8, 9, 5, 3, 1, 7, 0 };

IEnumerable<int> query =
source.Where(i => i >= 5)
.Select(i => i * 2);

foreach (var i in query)
Console.WriteLine(i);

In fact, you can see that there is a direct translation from the query expression to the same query that is expressed in method notation.  I believe that in early versions of the C# 3.0 compiler, this translation was implemented almost like a macro.  But in any case, queries that are implemented via method syntax rely, of course, on the extension methods that are included with the .NET framework, and hence query expressions also rely on them.  It is the ability to write extension methods for generic interfaces that enables queries.

[Blog Map]  [Table of Contents]  [Next Topic]