Advertisements
Home > ASP.NET > C# Tutorial – Extension Methods

C# Tutorial – Extension Methods


Today, we are going to take a look extension methods, which is a language feature introduced to C# in .NET 3.0. Extension methods are a piece of syntactic sugar that allow you add new functionality to a class that you don’t have direct access to. Sound cool yeah? Cause it is.

With C# before extension methods, it was common to have classes full of utility methods that mostly just augmented the functionally of some part of the .NET framework. Say, for instance, there were some other things that you thought would be handy to be able to do with strings whenever you wanted – perhaps you were needing to reverse the words in a string relatively often. You would probably write a class like this:

public static class StringUtils
{
public static string ReverseWords(string str, char sep)
{
char temp;
int left = 0, middle = 0;char[] chars = str.ToCharArray();
Array.Reverse(chars);for (int i = 0; i <= chars.Length; i++)
{
if (i != chars.Length && chars[i] != sep)
continue;

if (left == i || left + 1 == i)
{
left = i + 1;
continue;
}

middle = (i – left – 1) / 2 + left;

for (int j = i – 1; j > middle; j–, left++)
{
temp = chars[left];
chars[left] = chars[j];
chars[j] = temp;
}

left = i + 1;
}

return new String(chars);
}

public static string ReverseWords(string str)
{ return ReverseWords(str, ‘ ‘); }
}

And then, when you wanted to reverse the words in a string, you would call it like this:

string myString = “I Am A String”;string backwards = StringUtils.ReverseWords(myString);

This isn’t a bad technique, and it works well as long as you are the only one working in this code base. But say someone else comes along and also needs to reverse the words in a string. If you never told them about your StringUtils class, they might go off and write their own implementation – and now you end up with two implementations of the same thing in your codebase. Very sad.

It is to fix this problem, and to make your code read a little bit nicer, that extension methods come in. Wouldn’t it be handy if you could make ReverseWords just another method that hangs off of the string class? No more having to know where all the utility methods are – they would be hanging right off the class that they operate on! If you’ve been using .NET 3.5 at all, you have probably been using extension methods and not even knowing it. When you include the namespace System.Linq in your file (which .NET 3.5 does by default) you get about 3 dozen methods added onto the IEnumerable<T> interface. You can tell that a method is an extension method because Visual Studio intellisense will show them like this:

All the extension methods have that little blue down arrow as part of their icon, and the tooltip will have the word “(extension)” in front of the method name.

So now we want to make this ReverseWords function an extension method. It is actually only a single change. You want to change the method signature from what it currently is:

public static string ReverseWords(string str, char sep)

to this:

public static string ReverseWords(this string str, char sep)

That’s right, all you have to do is add ‘this‘ before the first argument. Now it is an extension method on whatever the type of the first argument is. So here is all of the new StringUtils code:

public static class StringUtils
{
public static string ReverseWords(this string str, char sep)
{
char temp;
int left = 0, middle = 0;char[] chars = str.ToCharArray();
Array.Reverse(chars);for (int i = 0; i <= chars.Length; i++)
{
if (i != chars.Length && chars[i] != sep)
continue;

if (left == i || left + 1 == i)
{
left = i + 1;
continue;
}

middle = (i – left – 1) / 2 + left;

for (int j = i – 1; j > middle; j–, left++)
{
temp = chars[left];
chars[left] = chars[j];
chars[j] = temp;
}

left = i + 1;
}

return new String(chars);
}

public static string ReverseWords(this string str)
{ return str.ReverseWords(‘ ‘); }
}

Now, you can do things like:

string myString = “I Am A String”;string backwards = myString.ReverseWords();

And it even shows up in intellisense:

Ok, now for some limitations of extension methods. You don’t get access to any of the actual innards of the class that you are writing the extension method for, so no access to any private or protected members. The extension methods must be declared inside of a static class, and they must be declared as static methods. In fact, you actually can still call the extension method directly – for instance:

string myString = “I Am A String”;string backwards = StringUtils.ReverseWords(myString);

That code will still work, even after ReverseWords was made an extension method. This makes a lot of sense in terms of backwards compatibility for people who had huge files of utility functions.

Another limitation is that you can’t override an existing method with an extension method. If the method already exists on the class, the extension method just won’t get called. The code will compile just fine, but it will always use the method that exists in the class. For instance:

public static Test
{
public static string ToString(this int val)
{  return “Ha Ha”; }
}int foo = 5;
Console.WriteLine(foo.ToString());

This will print out ’5′, and not ‘Ha Ha’ – and this is very good, otherwise people could be in for a world of confusion.

I mentioned a little bit earlier that using the ‘Linq’ namespace adds a whole bunch of methods to IEnumerable<T>. You might have wondered “But that is an interface! You can’t add methods with implementations to interfaces!” Well guess what – this is yet another handy feature of extension methods. You can add extension methods to interfaces, and every class that ever implements that interface suddenly has your new method. Very handy!

Advertisements
Categories: ASP.NET
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: