Introduction
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 the System.String
class, it could be called as if it was one of the System.String
class's built-in methods:
' VB |
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 <a href="URL">URL</a>
).
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.
' VB |
With the StringHelpers
wrapper class in place, I can exercise this added string functionality using code like:
' VB |
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 (StripHtml
, RemoveProfanity
, and ConvertUrlsToHyperlinks
) would be part of the System.String
type, and I could call them using a more intuitive syntax (StringVariable.StripHtml()
) 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 System.String class, for example, is marked as sealed , meaning that it cannot be extended. For more on using inheritance, see Ian Stallings article, Using Object-Orientation in ASP.NET: Inheritance. |
Creating Extension Methods for System.DateTime
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."
The System.DateTime
class has a number of formatting methods - ToString()
, ToShortDateString()
, and ToLongTimeString()
, to name a few - but wouldn't it be nice to have a method like 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 System.DateTime
class: ToRelativeToCurrentTimeString()
and ToRelativeToCurrentUtcTimeString()
. These methods will both operate on a DateTime
instance and return a string that displays a time description relative to the current time (or UTC time).
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 Extension()
attribute.
The following Module
named DateTimeHelpers
contains two methods: ToRelativeToCurrentTimeString(DateTime)
and ToRelativeToCurrentUtcTimeString(DateTime)
, both of which accept a DateTime
instance as their first input parameter. The methods are also marked with the Extension()
attribute (which is found in the System.Runtime.CompilerServices
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 DateTime
values.
Imports System.Runtime.CompilerServices |
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 ToRelativeToCurrentTimeString()
method is displayed in a Label Web control.
Extension Methods with Input Parameters | |
---|---|
The ToRelativeToCurrentTimeString() and ToRelativeToCurrentUtcTimeString() methods are defined in the Module as having one input parameter of type DateTime . This results in an extension method applied to the DateTime type that has no input parameters. But what if we needed to pass in one or more parameters to the ToRelativeToCurrentTimeString() ? For example, maybe we wanted to pass in some integer value like so: DateTimeInstance.ToRelativeToCurrentTimeString(someIntegerValue) . 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 Module
in C# is a static class
. Also, the methods in a static class
must be marked as static
, as well. Finally, instead of using the Extension()
attribute, C# requires that the this
keyword be used for the input parameter whose type the extension method will be applied.
using System; |
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 namespace (Helpers
) via the using
statement (i.e., using Helpers;
).
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 using namespace;
.
Conclusion
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.
Happy Programming!
Source: http://aspnet.4guysfromrolla.com/articles/120507-1.aspx#postadlink
No comments:
Post a Comment