Extension methods are an integral part of modern .NET and some of .NET’s best features such as LINQ. Unfortunately, a lot of developers get intimidated by them and don’t understand what’s going on under the surface or how to build new ones. In this article I’ll attempt to demystify extension methods and illustrate how they can be used to build elegant and fluent code.

The Basics: Static Methods

In order to discuss extension methods, we have to first discuss static methods.

A static method is simply a method declared with a static keyword. This tells .NET that the method operates not on a specific instance basis, but is attached to the class as a whole. Since these methods are static, they do not have access to the state of any specific instance unless it is passed in as a parameter to the method (more on this later).

The Integer.Parse method is a fairly well-known static method as is String.IsNullOrEmpty.

Over the course of this article we’ll be building out a method for getting information on books, so let’s create a static method that builds a list of books.

Now, to call out to get our books, we just do something like this:

var books = Books.GetBooks();

Pretty simple to use.

Extension Methods

Next let’s turn our attention to extension methods.

Put simply, extension methods are specially declared static methods that the compiler lets you call on objects matching their signature.

Let me show you what I mean.

Let’s say we have the following static method:

Here we can take any Book instance and pass it in to Books.IsBoring and get a boolean response.

Let’s change this to be an extension method.

Since extension methods can only be declared in static classes (classes which cannot be instantiated and have only static members), we need to add the static keyword to our class.

Now, we declare our IsBoring method to be an extension method by adding the this keyword to the first parameter like so:

What the this keyword is telling .NET is that IsBoring is an extension method and can either be invoked via the static method syntax like Books.IsBoring(someBook) or via an extension method syntax like someBook.IsBoring().

Note that the this keyword in the extension method syntax can only be used for the first parameter, which is the type or interface that the method extends.

Extension methods are syntactic sugar to have the compiler replace extension method style invocations to static method invocations.

The net result, however, is that extension methods let you appear to bolt on new functionality to other classes or interfaces. This is their primary advantage as extension methods allow you to simplify calling syntax at the cost of obscuring exactly where the method is declared to the casual reader.

Now that we know what extension methods are, let’s look at using them to build a fluent syntax or domain specific language.

Chaining Extension Methods Together

Let’s say you want to create a book and need to perform a number of operations in order to create a valid book. If you wanted to offer a fairly flexible and readable API, you could use extension methods to create a mini domain specific language (DSL).

In this example, our end goal is to create a book object that is customized based on the values we’ve configured.

Let’s focus on the end result first:

There’s a lot going on there, but maybe not as much as you think.

Let’s start with the Books.CreateBook call. This is a static method invocation that takes in a string representing a book’s title and return’s some mystery object.

Let’s call that object a BookBuilder and say that it looks something like this:

Okay, now this is making maybe a little more sense. That’d mean that our CreateBook static method would look something like:

Next our example has us calling WrittenBy. Well, the BookBuilder class doesn’t define that method. In a normal application we’d probably just add the method to BookBuilder, but that wouldn’t let us play with extension methods here, so let’s pretend that the BookBuilder class is defined by some code we don’t control and can’t modify.

We’ll handle the WrittenBy method by adding an extension method:

This is a very simple method, but there’s some key things going on here.

First, the method acts as an extension method on BookBuilder instances due to the this keyword in the parameter signature.

Second, the method is invoked with only one parameter specified (e.g. WrittenBy("Michael Crichton") because the first parameter is inferred based on the BookBuilder you’re invoking the extension method on.

Third, we’re returning the same builder instance we got back. The reason why we return this parameter is entirely to support fluent syntax like we saw in the example earlier, and allow invoking extension methods on the return result of prior extension methods.

The final static class might look something like this:

That might not look like the prettiest code you’ve ever seen, but the type of syntax it can create can be incredibly powerful and beautiful.

Let’s Talk about LINQ

Extension Methods were added to the C# language explicitly in order to support Language Integrated Query (LINQ) in .NET Framework 3.5.

LINQ is one of my favorite features of C# in terms of developer productivity, and none of that would have been possible without extension methods.

LINQ lets you do things like:

Maybe this is a little bit of a silly example, but this all works by having extension methods that take in IEnumerable<T> or IQueryable<T> and use various Func signatures to filter, sort, or transform the collection.

Put another way, if you really wanted to, you could write your own version of LINQ with about the exact same syntax using extension methods. Please don’t do this – Microsoft did a great job already – but the capabilities of extension methods allow you to do this.

Closing Thoughts

Hopefully this demystifies some of the magic behind extension methods, LINQ, and static vs instance methods.

I am convinced that extension methods (and LINQ by extension) are one of the key productivity gains of .NET technologies, alongside things like the base class library, the common language runtime, Visual Studio, and generics.

While you may not create or even think about extension methods, they power a lot of what we do in modern .NET and the flexibilty they offer can be a tool for good.

Tags:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.