Extending Base Type Functionality with Extension MethodsBy Scott Mitchell
In November 2007, Microsoft released the .NET Framework version 3.5, Visual Studio 2008, and new versions of the C# and Visual Basic languages (see An Overview of ASP.NET 3.5 and Visual Studio 2008 for more details on the release). The new C# and Visual Basic versions include a myriad of exciting new features that make the languages more expressive and open the door for new syntax constructs, like LINQ. One of these new language features is extension methods, which is the topic for today's article.
Extension methods allow a developer to tack on her own methods to an existing class in the .NET Framework. For example,
imagine that our developer created a method named
StripHtml, that strips HTML elements from a string using a
regular expression. By associating this method with
System.String class, it could be called as if it was one of the
Extension methods make it easy to add functionality to an existing type using a natural syntax. Also, since the extension methods appear in Visual Studio's IntelliSense drop-down list, they are easier to find and use than wrapper class equivalents. In this article we will see how to create extension methods in both C# and Visual Basic. Read on to learn more!
The Impetus Behind Extension Methods
Over the past several years, I've worked with a number of clients in building large ASP.NET web applications. In most of these applications there has been a need to define extra functionality on strings. On some pages we need to strip all of the HTML elements from a string before displaying it; on other pages we need to parse the string and censor out an potentially profane words; and on other pages we need to convert URLs into appropriate HTML anchor tags (i.e., converting the text URL into
To provide this function I created a wrapper class named
StringHelpers with methods for stripping HTML elements, censoring profanity,
and converting URLs into hyperlinks. The wrapper class was implemented as a class with a series of static methods that
accepted a string as input, perform the intended operation, and then return the resulting string.
StringHelpers wrapper class in place, I can exercise this added string functionality using code like:
While wrapper classes offer a simple approach to encapsulate commonly used functionality, there is no tight association between
the wrapper class's functionality and the type its methods operate on. In order to use the wrapper class, a developer must
first know of its existence; he must dig into the various methods to see how they operate. Ideally, these string-specific methods
ConvertUrlsToHyperlinks) would be part of the
System.String type, and I could call them using a more intuitive syntax (
and enjoy IntelliSense support through Visual Studio.
Extension methods provide these advantages, allowing a developer to more intuitively assign methods to a particular type.
|Extending Type Functionality via Inheritance|
In addition to wrapper classes, another common approach to adding functionality to an existing type is through
inheritance. Inhertiance is a core object-oriented programming principle that enables a developer to take an existing
type and extend its functionality by adding new methods, properties, and events. The downside with inheritance is that you need
to create a new type to extend the existing type. Consequently, in order to use the added functionality you have to
work with the new type. This is a Good Thing and appropriate design in most cases, but if you just want to add a simple
method or two to add new functionality to an existing type, having to use the newly created type can be burdensome. Moreover, not all types
can be extended. The |
For more on using inheritance, see Ian Stallings article, Using Object-Orientation in ASP.NET: Inheritance.
Creating Extension Methods for
Let's look at how to create and use extension methods. Many online messageboard sites - like the ASP.NET Forums - display the times the messages were posted using descriptions relative to the current date and time (rather than simply displaying the full date and time). For example, if a post was made within the last minute, the post's date value might read: "Seconds ago." Alternatively, if the post happened in the past few minutes, the message might read: "3 minutes ago." If the post happened within the current date, it might just show the time, like: "10:34 AM". If the post happened in a prior day, then the entire date and time would be displayed: "December 3rd, 2007 10:34 AM."
System.DateTime class has a number of formatting methods -
ToLongTimeString(), to name a few - but wouldn't it be nice to have a method
ToRelativeToCurrentTimeString() method that effected the logic described above? We can add such a method
using extension methods. Let's create two such extension methods on the
ToRelativeToCurrentUtcTimeString(). These methods will both operate on a
and return a string that displays a time description relative to the current time (or UTC
Since the syntax for creating extension methods differs quite a bit between VB and C#, let's examine first implement these extension methods using VB; after doing so, we will create the extension methods in C#. The download at the end of this article includes two ASP.NET website applications, either of which you can open with Visual Studio 2008: one in VB and one in C#.
Creating the Extension Methods with Visual Basic
In order to create the extension methods in Visual Basic we need to first create a
Module. For each extension method you want to create, add a method whose first input parameter is of the type that you want to add the extension method to. Moreover, prefix the method with the
DateTimeHelpers contains two methods:
ToRelativeToCurrentUtcTimeString(DateTime), both of which accept a
DateTime instance as
their first input parameter. The methods are also marked with the
attribute (which is found
namespace). The two methods call the private
ToRelativeString method, which returns the appropriate
string message based on the difference in time between the two passed-in
We can now call these extension methods from a
DateTime instance. In order to use an extension method, we
first need to add an
Imports directive to the code file, importing the namespace where the extension
methods reside (
Helpers). Upon doing that, the extension method is visible in the IntelliSense drop-down list,
as the following screen shot illustrates.
The download at the end of this article includes a demo that allows the visitor to enter a date and time value into a TextBox.
On postback, the entered value is converted into a
DateTime and the return value from the
method is displayed in a Label Web control.
|Extension Methods with Input Parameters|
To accomplish this, simply update the definition of the
The order of the input parameter's are important with extension methods, because the first parameter is the type
that the extension method is applied to. In other words, if you redefined the extension method so that the
Creating the Extension Methods with C#
The syntax for creating the extension methods in C# is a little different than in Visual Basic. The equivalent of a
Modulein C# is a
static class. Also, the methods in a
static classmust be marked as
static, as well. Finally, instead of using the
Extension()attribute, C# requires that the
thiskeyword be used for the input parameter whose type the extension method will be applied.
With the extension methods defined, they can be used in code as if they were native members on the underlying type.
Like with the Visual Basic example, in order to use the extension methods in a code file you must import the appropriate
Helpers) via the
using statement (i.e.,
Things to Remember When Using Extension Methods
When using extension methods there are a few things to keep in mind. First, realize that extension methods are simply syntactic sugar - they do not introduce any new functionality, but just provide existing functionality in a more human-friendly syntax. Underneath the covers, the design-time experience allows for the IntelliSense functionality, but in actuality an extension method call is compiled into a call to the appropriate method in the static class or
Module. In other words, extension methods are synonymous with wrapper classes - the only difference is the design-time syntax.
Since extension methods are functionality equivalent to wrapper classes, the same limitations apply. A wrapper class, for instance, can only access public members of the types it is working with. Likewise, an extension method defined on a type can only work with those types public members. It cannot read or write protected members (which is possible with inheritance). Moreover, extension methods can only be applied to methods - there is no such thing as an extension property or an extension event.
Finally, don't forget that in order to use an extension method you must import the appropriate namespace into your code.
In VB that means you'll need to do an
Import namespace. In C# it's
In this article we looked at a new feature in C# 3.0 and Visual Basic 9.0: extension methods. We saw how to create and use a simple extension method in both C# and VB. The download at the end of this article includes the code examined in this article along with a simple demo application illustrating the extension method is use.