Introduction
It is nice to see that people like my post so much. Ever since I wrote about “Internals of Delegates”, there are large number of hits on my site and people wanted me to continue posting few more internals like that. Even I was thinking the same, I was confused about what I should start for my next topic. Finally, I have decided to speak about another important C# feature that we use very often called Extension
methods and try to look deep into its facts. Let's first demonstrate the basics of Extension
methods first and later we will dive deep into it. If you are comfortable with Extension
methods, please skip the following section.
The Basics
Extension
method is actually defined as static
but acts as an instance specific method. In other words, even though the code that is running inside the Extension
method is not declared within the scope of the class, it is still associated with an instance of an object for that particular class. Extension
method does not need to be in the same namespace where the actual type is. Hence you can easily add extension method anywhere outside the namespace and any other static
class. The namespace which when added to the code will automatically add those extension methods and call appropriately for an existing type. Extension
methods can also be thought as extension to a pre-existing type.
For instance, let me define a class first:
public class MyClass
{
public int MyMethod()
{
Random rand = new Random(100);
return rand.Next();
}
}
This is a very simple class with one method MyMethod
which returns an integer value. Now how to extend the class to add another method say MyMethod2
. There are a couple of option available for you, either you need to extend this class to another type MyClass2
derived from MyClass
and include that method into it, or use extension
method to add it directly within the type MyClass
itself.
public static class Extensions
{
public static int MyMethod2(this MyClass obj)
{
return 10;
}
}
MyMethod2
is now an extension method which is included with MyClass
. You should remember that Extension
method is static
with the first argument being of Type
in which the method is to be included with a “this
” keyword in front of it. This identifies it as an extension
method. Any parameter can be passed normally after the first argument.
By the way, you can even make MyClass
sealed (not extensible), yet you have the option to use extension method to extend the type.
Note: By using extension method you can extend any type, even from the BCL.
Calling an Extension Method
Well, there is nothing as simple as we could speak about calling an extension method. There is no extra thing that you need to do when you call an extension method. Extension
method is called just the same way as you call a normal instance method. The compiler automatically replaces the call to provide appropriate method binding.
MyClass tobj = new MyClass();
Console.WriteLine("Value from Instance method : {0}",tobj.MyMethod());
Console.WriteLine("Value from Extension method : {0}", tobj.MyMethod2());
Console.Read();
You can even add extension method to any known Types.
public static byte[] GetBytes(this string thestring)
{
return Encoding.ASCII.GetBytes(thestring);
}
Here every string
you declare will automatically add GetBytes
method into it.
Internals of Extension Method
Now as you know the basics of Extension
methods, let's go a little depth. The first thing that I would like to share with you is how a method is actually called in IL for extension method.
MyClass tobj = new MyClass();
tobj.MyMethod();
tobj.MyMethod2();
Extensions.MyMethod2(tobj);
Now let us look into three calls in IL.
So if you demonstrate the three lines in IL, it is evident that the last two calls are exactly the same while the first is instance specific call. The C# compiler translates the call exactly the same way as if we call the static
method directly. The first call is the general call to the MyMethod
member, which uses callvirt
(to ensure it is latebound) while the next two methods invokes a call (strictly compile time bound).
So what is the main advantage of having extension method then if it produces the same MSIL as if we do call it normally? Is there any specific advantage we get if we create an extension method ? Let's demonstrate the IL for Extensions
class.
We put two methods in Extensions
class, such that the class looks like:
public static class Extensions
{
public static int MyMethod1(MyClass obj)
{
return 10;
}
public static int MyMethod2(this MyClass obj)
{
return 10;
}
}
So the MyMethod1
is the same replica to MyMethod2
, the only difference is that MyMethod2
is an extension method. Now if you dissemble the code, it will look like:
You should notice, in the actual IL, the only thing that differentiates between the two methods is the presence of ExtensionAttribute
in MyMethod2
. MyMethod2
creates an object of custom ExtensionAttribute
class.
So you should be clear, the compiler just puts an ExtensionAttribute
to both the class and the Extension
method and the code that I think might produce this IL would look like:
[Extension]
public static class Extensions
{
public static int MyMethod1(MyClass obj)
{
return 10;
}
[Extension]
public static int MyMethod2(MyClass obj)
{
return 10;
}
}
Strange rules to the compiler, C# gives you an error saying you should not use Extension
attribute, rather use this syntax instead.
Now as we get through with this, let's demonstrate the power of the compiler while translating the Extension
methods into IL. Let me cast the method into a delegate.
Func<int> action = tobj.MyMethod2;
object t = action.Target;
Console.WriteLine(t);
If you see the output to this, its MyClass
rather than null
. Now let's see how IL looks like:
Again, this is very unnatural. The compiler again writes this for us. The delegate Func
receives the object as first argument (as Target). Hence the Target for extension method behaves appropriately (as instance method). Neato!!!
[Note: Does it relates to Adapter Pattern?]
Just few minutes back Zenwalker asked me about the relationship between Adapter pattern and Extension Methods. Well, in fact I think there is no relation between the two, even though both creates Type wrappers. Adapter pattern being a design pattern introduces Wrappers to make one type compatible with another using a common interface between the two; While Extension methods is language feature and it allows a type to extend its hierarchy.
Conclusion
That’s all, folks. Even though I tried a little more to check MethodInfo.GetCurrentMethod()
it seems to be nothing to talk about. Extension
method is a language feature (not a CLI change) and the Microsoft guys did great to make it more useful. I liked it.
Thanks for reading.