A number of articles I’ve read recently have mentioned “Extension methods” in passing, yet it is difficult to find out what this is, if you don’t already know.
A few searches, however, did turn up three good sources: MSDN provides this reference page, then I found a classic “Gu” blog post from March of ’07, and finally, the incredible Pete Brown tackles Extension methods as well.
This mini-tutorial will attempt to fill in the details and focus on two key uses of Extension Methods:
- To add functionality to a class you don’t own
- To enable method-based queries (using lambda expressions) in Linq
Adding Functionality to a Class You Don’t Own
Programmers are often faced with wishing that a given class had a method that the designer of the class did not supply. If the class is not sealed, you can derive a specialized version that has your method, but many framework classes are sealed. You can write around this problem, but it would be nice to create a method that looks like it is part of the original class, and Extension methods let you do just that.
Adding LastN to String
It is certainly possible to get the last n characters from a string, but it is a little tedious. The traditional way to do so (broken out into fragments so that the steps are obvious) is shown in this very small Silverlight application,
Here is the click handler for GoButton (you’ll be able to deduce the names of the other controls),
void GoButton_Click( object sender, RoutedEventArgs e ) { string target = StringToParse.Text; int howMany = Convert.ToInt32( NumberToGet.Text ); string retString = string.Empty; if ( howMany <= target.Length ) retString = target.Substring( target.Length - howMany, howMany); ResultBox.Text = retString; }
Extending String
It would be nice, especially if we are going to be doing this a lot, if the String class had a Right() method so that we could shorten this listing to
void GoButton_Click( object sender, RoutedEventArgs e ) { string target = StringToParse.Text; int howMany = Convert.ToInt32( NumberToGet.Text ); ResultBox.Text = target.Right( howMany ); }
While the actual savings may not be that great, the code is far easier to understand (and thus maintain).
Some Like It Terse
I must confess the old C programmer in me wants to rewrite this as
void GoButton_Click( object sender, RoutedEventArgs e ) { ResultBox.Text = StringToParse.Text.Right(
Convert.ToInt32 (NumberToGet.Text )); }
While I would have eschewed such a compressed style in the past as forfeiting any chance to see the interim variables, the debugger is now quite sophisticated, and has no trouble providing the information needed,
Creating the Extended Method
The example above works because I created an extended method for the String class. This is done by creating a static method, typically in a static class. That method must have as its first variable a parameter declared in three parts:
- the key word this
- the type you are extending
- an instance identifier
It can then have any other “normal” parameters you care to give it. The extended method Right was thus created (in a file named Extensions.cs as follows:
namespace GetLastNFromString { public static class Extensions { public static string Right( this string s, int howMany ) { if ( howMany <= s.Length ) return s.Substring( s.Length - howMany, howMany ); else return s; } } }
The “else” statement is arbitrary; here I choose to return the original string if I can’t return the requested portion (e.g., the user asks for the right most 10 characters of an 8 character string. Alternative solutions are to return string.empty, null or, if you insist, to throw an exception.
(I normally would put the if and the else in braces as well (you never know when you’ll add more code) but I’ve left them out here to save space.
Extension Methods and LINQ
In the next column I’ll tackle the second primary use of Extension methods, enabling method-based LINQ queries using Lambda expressions.
Next Extension Methods and Lambda Expressions