Demystifying C# 3.0 - Part 3: Extension Methods

Posted on 6/30/2006 @ 8:41 PM in #Vanilla .NET by | Feedback | 13080 views

If you've been following my blog, you would have noticed that I've been trying to talk about new C# 3.0 features one by one. I am trying to take the technical jargon out, and bring these features down to an understandable level.

You may want to read the two features I have already talked about below -

a) Demystifying C# 3.0 - Part 1: Implicitly Typed Local Variables "var"
b) Demystifying C# 3.0 - Part 2: Anonymous Types

So here goes, Part 3: Extension methods.

Frequently you are handed a class, such as System.String, or System.Int32, that you "wished" had that one extra method that would make your life so much easier - but damn it doesn't have that method. In certain instances you can inherit and add, but you know that is tougher than it sounds in many cases (abstract/virtual), and in certain cases impossible (sealed).

Extension methods, solve that problem. You can now add newer methods, specific to your business domain - to existing types, that you did or didn't write.

So if you wanted an extra method called "SpankMonkey", you could now write code like below

int i = 10 ;
i.SpankMonkey() ; // Spanks the monkey per the logic you wrote.

How neat !!! But don't go around misusing this *feature*, because Extension methods are both less discoverable and more limited in functionality than plain vanilla instance methods such as ToString(). Use them only if you must.

So how do you write an extension method?

Well thats easy, you simply put the "this" keyword as the first parameter of the extension method ~ which is a static method in a class. So you could write code as below

public static class myExtensions
{
   public static void SpankMonkey(this int i)
   {
      Console.WriteLine("SPANK!!");
   }
}

Sure you could have complicated implementations such as -

public static int DoubleMe(this int i)
{
   return i + i ;
}

You could call the above using -

int i = 10;
Console.WriteLine(i.DoubleMe()) ; // Prints 20

You could also pass in a "generic" instead of an "int" or "string" etc.

Extension Method Resolution:

An obvious question here is, what if your class implements a method, AND there is an extension method that looks, talks, walks the same way - that is of the same name? Which gets called?

The answer is - "Whichever is the closest". In other words,

Strongly Typed instance methods _will_overrule_
Strongly Typed extension methods _will_overrule_
Not Strongly Typed instance methods _will_overrule_
Not Strongly Typed extension methods.

Whoaa that's confusing. :)

This code makes it easy to eat the above 4 lines.

public static class E
{
    public static void F(this object obj, int i) { }
    public static void F(this object obj, string s) { }
} 

public class A { }

 

public class B

{

    public void F(int i) { }

}

public class C

{

    public void F(object obj) { }

}

public class X

{

    public static void Test(A a, B b, C c)

    {

        a.F(1);               // E.F(object, int) is called

        a.F("hello");         // E.F(object, string) is called

        b.F(1);               // B.F(int) is called

        b.F("hello");         // E.F(object, string) is called

        c.F(1);               // C.F(object) is called

        c.F("hello");         // C.F(object) is called

    }

}

Of course if nothing matches, you get a compile time error (duh!)

Neat !! So now we know what "Extension methods" are, how you can write them, how you can use them, and how they may be called.

Next we'll be talking about Lambda Expressions. See ya around !! :-)

 

Sound off but keep it civil:

Older comments..


On 12/4/2007 4:48:19 AM Indrajit said ..
But whats the important use of Extension Methods?

On 1/5/2008 10:25:01 PM Mahesh said ..
If given a choice, partial method or extensions method, which one should be preferred?


On 3/10/2008 5:28:03 AM Zeeshan said ..
c.F(1); // C.F(object) is called


c.F("hello"); // C.F(object) is called


C doesn't have Strongly Typed Instance method but E does? so shouldn't it be like:


c.F(1); // E.F(object, int) is called


c.F("hello"); // E.F(object, string) is called


On 3/18/2008 5:05:24 PM Doug said ..
Nice explanation! Hope you continue to write these.


On 4/1/2008 6:28:02 AM Nitin Reddy Katkam said ..
Zeeshan,

Extension methods work a little differently so although we might expect to see E.F being called when calling c.F, it is actually C.F.

-Nitin


On 10/14/2008 8:41:36 AM Jamie said ..
A good example of where this comes in handy might be processing old flat files. I had to do this recently at work. The flat file format I had to process used COBOL formatted numbers. It would have really been nice if I could have extended String to include a FromCobol method that returns a decimal value, and a ToCobol method that takes a decimal, and converts it to a COBOL string representation of that number. But alas, we're still using 2.0 at work...


On 10/14/2008 7:06:30 PM KM said ..
Below lines are quite confusing:


" Strongly Typed instance methods _will_overrule_


Strongly Typed extension methods _will_overrule_


Not Strongly Typed instance methods _will_overrule_


Not Strongly Typed extension methods. "

Just to elaborate:


It will call its own member irrespective of strongly typed or not strongly typed. b.F("hello"); calls "E.F(object, string)" because b doesn't have definition of F(string) so it have to call next match. If it doesn't have any then it will call the nearest matching signature i.e strongly typed.

Thanks & Appreciate your effort for writing this series of demystifying C#3.0.


On 11/30/2008 7:21:43 AM Yoann. B said ..
Hi,

Interesting, you should take a look at the Extension Library on CodePlex : http://www.codeplex.com/Sb2Extensions


On 1/1/2009 10:08:56 AM Lars Nielsen said ..
I can imagine these are useful but there is scope for misuse of extension methods. In the extreme case, why bother to create classes at all? Just add hundreds of extension methods to the Object class and you can bypass strong typing completely! Where should you create extension methods?

In the last example the extension method is defined in class E but this class is not actually referenced anywhere in the Main method, nor is it related to A,B or C. It seems to be just a random place in which to put an extension method? I'd suggest all extension methods in project should be in a single class file so as to make them easy to find, otherwise code could become hard to follow.


On 3/19/2009 10:09:03 AM Manuel Pettersson said ..
Zeeshan you ask,


"C doesn't have Strongly Typed Instance method but E does? so shouldn't it be like:


c.F(1); // E.F(object, int) is called"

I think extension methods being strongly typed refers to the class they extend, not the argument. And the method F(this object obj, int i) declared in E extends object, thus it's not strongly typed.


On 9/19/2010 5:14:56 PM Experts Comment said ..
Here is a link that provide good explanation of Extension method and its usage.

http://www.a2zmenu.com/CSharp/CSharp-Extension-Method.aspx