Skip to main content

...

....

C# Tutorial - Extension Methods [Beginner]


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\ interface. You can tell that a method is an extension method because Visual Studio intellisense will show them like this:
Intellisense Extension Methods
Example 

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:
Our New Extension
Method 

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!

Well, that is it for my rambling on about extension methods for today.

Source Files:

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >();

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV