http://www.developer.com/net/csharp/article.php/3592216/Using-the-New-Extension-Methods-Feature-in-C-30.htm
One of the numerous exciting new features in C# 3.0 is extension methods: static methods that you can invoke using the instance method syntax. This article discusses this new feature in detail with sample code and recommendations for best use. (My previous article on C# 3.0 discussed anonymous types, another of the new features.) Extension method behavior is similar to that of static methods. You can declare them only in static classes. To declare an extension method, you specify the keyword this as the first parameter of the method, for example: To compile the above code, you need to install Visual Studio 2005 and the LINQ preview. If you have Visual Studio 2005 installed already, you have three new project templates in the LINQ Preview under Visual C#: LINQ Console Application, LINQ Windows Application, and LINQ Library. Take the following steps to compile the code: If you have only .NET 2.0 installed, you can do a command-line compile by using the following command: As you can see from the above snippet, the differences between the extension method (ToInt32Ext) and the regular static method (ToInt32Static) are the following: Extension methods, though static in nature, can be called only on instances. Trying to call them on a class will result in compilation errors. The class instances on which they are called are determined by the first argument in the declaration, the one having the keyword this. If you look at the IL generated from the executable compiled previously, you will see the display in Figure 1. Figure 1. Extension Methods IL The following is the IL for the extension method ToInt32Ext: The following is the IL for the static method ToInt32Static: The code marked in red is present in the extension method: .custom instance void: This line indicates that this method applies to instances only. [System.Query]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ): This line indicates that the Extension attribute is flagged. Table 1 shows how the method invocations are modified when the code is compiled. Table 1. Method Invocation Modifications at Compile Time If you check the IL of the main method through ILDASM, it will appear as follows: The code marked in red indicates that the above method conversion (expr . identifier ( ) <--> identifier (expr) ) occurred. So, when you call int i = s.ToInt32Ext();, the compiler internals convert it to int i = EMClass.ToInt32Ext(s);. Then, the rewritten form is processed as a static method invocation. The identifier is resolved in the following order: The following is the order of precedence for methods in descending order: You may be asking, "Why should I use extension methods when I have the regular static and instance methods?" Well, the answer simply is utter convenience. Let me explain with an example. Suppose you developed a library of functions over a period of years. Now, when someone wants to use that function library, the consumer must know the class name that defines the desired static method. Something like the following, for example: At this point, IntelliSense will pop in and give you the names of the available functions. You just have to pick the one you need. You then type your desired methods and pass the necessary argument: With this approach, you need to know beforehand which library contains your desired function and its name. With extension methods, it is more natural—something like the following: At this point, IntelliSense pops up and shows which extension methods are available. You simply type the extension method you want: No arguments are needed to identity the data type on which this method needs to work. Extension methods provide a new mechanism for invoking static methods on object instances. But, as per C# 3.0 language specifications, extension methods are less discoverable and more limited in functionality than instance methods. Therefore, you should use extension methods sparingly, only where instance methods are not feasible. Also, C# 3.0 is not yet an official release, so its specifications are not finalized. Therefore, the syntax is liable to change. You download the source code for this article here. Vipul Patel is a Microsoft MVP (two years in a row) in Visual C# and currently works at Microsoft through Volt Information Sciences. He specializes in C# and deployment issues. You can reach him at Vipul_d_patel@hotmail.com.
Using the New Extension Methods Feature in C# 3.0
March 20, 2006
Declaring Extension Methods
// Program.cs
public static class EMClass
{
public static int ToInt32Ext(this string s)
{
return Int32.Parse(s);
}
public static int ToInt32Static(string s)
{
return Int32.Parse(s);
}
}
class Program
{
static void Main(string[] args)
{
string s = "9";
int i = s.ToInt32Ext(); // LINE A
Console.WriteLine(i);
int j = EMClass.ToInt32Static(s); // LINE B
Console.WriteLine(j);
Console.ReadLine();
}
}
Csc.exe /reference:"C:\Program Files\LINQ Preview\Bin
\System.Data.DLINQ.dll"
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll
/reference:"C:\Program Files\LINQ Preview\Bin\System.Query.dll"
/reference:"C:\Program Files\LINQ Preview\Bin\System.Xml.XLINQ.dll"
/target:exe Program.cs
Inside the IL
Click here for a larger image.
.method public hidebysig static int32 ToInt32Ext(string s) cil managed
{
.custom instance void [System.Query]System.Runtime
.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call int32 [mscorlib]System.Int32::Parse(string)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method EMClass::ToInt32Ext
.method public hidebysig static int32 ToInt32Static(string s) cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call int32 [mscorlib]System.Int32::Parse(string)
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method EMClass::ToInt32Static
Extension Method Invocations
Sr #
Method Invocation
Code Compiled As 1
expr . identifier ( )
identifier (expr) 2
expr . identifier ( args )
identifier (expr, args) 3
expr . identifier <typeargs> ( )
identifier <typeargs> (expr) 4
expr . identifier <typeargs> ( args )
identifier <typeargs> (expr, args)
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 42 (0x2a)
.maxstack 1
.locals init ([0] string s,
[1] int32 i,
[2] int32 j)
IL_0000: nop
IL_0001: ldstr "9"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call int32 ExtensionMethods.EMClass::
ToInt32Ext(string)
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0014: nop
IL_0015: ldloc.0
IL_0016: call int32 ExtensionMethods.EMClass::
ToInt32Static(string)
IL_001b: stloc.2
IL_001c: ldloc.2
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: nop
IL_0023: call string [mscorlib]System.Console::ReadLine()
IL_0028: pop
IL_0029: ret
} // end of method Program::Main
Why Use Extension Methods?
a = MyLibraryClass.
a = MyLibraryClass.DesiredFunction(strName)
a = strName.
a = strName.DesiredFunction()
Invoke Static Methods on Object Instances
References
Download the Code
About the Author