Visual Studio 2008 Extension Methods

This is excerpt about this blog post!

Published on Tuesday, January 8, 2008

Now that visual studio.net 2008 has been released developers have a much improved development environment and framework to produce high quality code with.  Extension methods are one of the new framework and IDE features that provides a powerful and clever method of extending objects that you do not have source code for or otherwise can't directly extend.

Simply put, extension methods allow you to add new methods to the public contract of an existing type without sub-classing, decorating or recompiling the original type.  Prior to this release there were a few options available to solve this problem.

The Decorator Pattern

The decorator is a great design pattern for extending the functionality of an object without sub-classing.  Without going into the nitty gritty details of decorator implementation, essentially you create an object that takes the object that you want to decorate as an argument to your new objects constructor.  Next, you'd create whatever methods you need in your object, accessing the "decorated" object as needed.

Using this pattern, you can extended the functionality of an existing object without subclasing or resorting to libraries of static methods.  Unfortunately this pattern is overkill for minor object extensions or use with value types.  I commonly use this pattern to create read-only versions of objects without having to change the functionality of the underlying object.  Another great example are the various stream objects in the System.IO namespace.

Subclassing

This option is self explainatory.  Simply create an object that inherits from the object you want to extend and add additional functionality.  Unfortunately if your object to extend is sealed you'll need to use a decorator or the dreaded "helper".

The "Helper" Object

Nearly every piece of software that I've ever supported has one or fifty of these objects.  I've seen string helpers, integer helpers, business object helpers, User Interface helpers, and ADO.NET helpers to name just a few.

Personally I don't care for this technique, though it can be extremely effective for minor object extension or use with value types.  It is susceptible to abuse through massive overloading, lack of commenting and documentation and poor overall design.

Enter the Extension Method

Essentially, these methods are similar to the static methods used in the helper object with one very important distinction; they exist as methods defined as part of the contract of the defined type.

public static class Extensions {
    public static bool InRange(this T value, T lower, T upper) where T : struct, IComparable {
        if(value.CompareTo(lower) >= 0 && value.CompareTo(upper) <= 0) {
            return true;
        }
        return false;
    }
}

In this example I've illustrated a very powerful generic method that allows a developer to see if a value falls into a range of acceptable values.  Because it is generic and constrained by the IComparable interface we have the ability to perform a comparison using the CompareTo(T) method exposed by the interface.  Syntactically, this is nearly identical to a standard static method with the exception of the this keyword that decorates the first argument of the method.  The this keyword tells the compiler that this method should be added to structs of type T (the generic type identifier).Using this new method is simple.

decimal price = 12.99;
if(price.InRange(1, 49.95)){
    Console.WriteLine("The price specified is within the specified range.");

}else{
    Console.WriteLine("The price specified is not within the specified range.");
}

This particular extension method is configured using the decimal type, though it will work for any struct that implements the IClomparable interface.  What's important is that visual studio.net 2008 will display this method using intellisense on objects that match both the this (generic) declaration as well as the interface constraint.There are countless applications for extension methods.  They provide a more intuitive method of extending objects without resorting to other techniques that might require extensive design consideration.