Sunday, February 5, 2012

Extension Methods in C#

Extension Methods (C#)

            Extension methods were introduced in C# 3.0, and provided a way to extend existing types. Wait a minute did I used “extend”? So what is the deal we have been extending classes since ages, using inheritance? Ok consider a class (this can be an inbuilt class in the .net library or your own class) and it is marked as sealed. Now you want to add few useful methods to this class. How would you do that? This is the perfect scenario where extensions methods can be utilized. So, “Extending an existing type other than the way of inheritance” would be a suitable definition for extension methods.
     Let’s consider an example, where you always want the initials of each name being entered to the system. So if you are entering “Rahul Dhammy”, the system would accept only RD. The first approach would be to create a static utility method which returns these two initials. That’s great but what if there are hundreds of names whose initials are to be taken. Your code would be something like this in that scenario

static void Main(string[] args)
{
Utilities.GetNameInitials(“Rahul Dhammy”);
Utilities.GetNameInitials(“Frank Matthews”);
.
.
.
… n number of names.
}

static class Utilities
{
public static string GetNameInitials(string str)
{
string initials = string.Empty;
string[] fullName = str.Split("".ToCharArray(),                                  StringSplitOptions.RemoveEmptyEntries);
          foreach (string inital in fullName)
          {
               initials = initials + st.Substring(0,1);
          }
          return initials;
}
}

Would it not be handy and clean if you don’t have to call the method in utilities class? Imagine your string class itself has this magical function. This is all possible using extension methods. So we will add one method to the string class or in other words we will be extending the string class. Since string class is sealed so we are going to make use of extension method.
Below is the modified GetNameInitials method:-

static class Utilities
{
public static string GetNameInitials(this string str)
{   
string initials = string.Empty;
string[] fullName = str.Split("".ToCharArray(),                                  StringSplitOptions.RemoveEmptyEntries);
          foreach (string inital in fullName)
          {
               initials = initials + st.Substring(0,1);
          }
          return initials;
}
}

The only difference between the GetNameInitials() method is the “this” keyword. It tells the compiler that it is an extension method for the class specified just after the keyword this (which happens to be string in this case).

This is how we can call it in the main program:

static void Main(string[] args)
{
           
string initials="Rahul Dhammy".GetNameInitials();
}

Great! it looks like we have the above functionality in the string class. Also when you do an intellisense for this method (by placing dot after the string) you will see a small arrow before the name, it tells us this is an extension method.


Experimenting and framing rules
Having learned the basics lets experiment a bit.
1)      Try removing the static keyword from the Utilities class. The program would give a compiler error “Extension method must be defined in a non-generic static class”. So this gives us the first protocol for using extension method, that they must be used in a static container (class).
2)      Let’s remove the static keyword from the method name GetNameInitials(). The compiler would again scream. “Extension methods must be static.” This gives us our second rule.
3)      I tried to look upon what exactly is the difference in the MSIL generated. I noticed that ExtensionAttribute is the only thing added to the extension method which tells the compiler that it is an extension method.


So there is no benefit in terms of execution which we are getting from extension method, extension methods have been given just as a short and sweet way of doing thing. In fact it is treated by compiler as just another static method.
 4) Try adding another method with the same name as extension method but without this keyword, the compiler would again give the error message “Method name already exists”. This shows that extension methods are treated as any other static method. You can further check the MSIL of a static method and extended method (with same functionality), the MSIL would be same except for the ExtensionAttribute hooked to it.

            Having said all good things about extension methods, it should be noted that extension methods should be used only when it is not possible to use instance methods. For example if you have a third party library and you cannot use their classes, because they are not available for inheritance. Using extension methods for type of tasks such as manipulating strings etc should be avoided. The reason I feel for this is at some point of time it would be difficult to understand as to where this method is coming from?
So extension methods though handy could introduce bad style of programming and coding practices and hence should be judiciously used.
Any discussions, improvements, corrections to everything said about extension methods would be highly appreciated.

No comments:

Post a Comment