先看一个扩展方法的例子:
1 class Program
2 {
3 public static void Main()
4 {
5 Int32 myNum = 1;
6 myNum = myNum.AddToOldNum(1);
7 Console.WriteLine(myNum);
8 }
9 }
10
11 public static class ExpandInt
12 {
13 //扩展方法必须为静态方法
14 public static int AddToOldNum(this int oldNum,int newNum)
15 {
16 return oldNum + newNum;
17 }
18 }
为一个类型扩展一个方法如此只简单,但是它究竟为我们做了什么呢,为什么我可以调用的AddToOldNum方法?还是让我们从IL代码层面来看看吧。
这里是上面代码编译的IL:
1 .method public hidebysig static int32 AddToOldNum(
2 int32 oldNum, int32 newNum) cil managed
3 {
4 .custom instance void [System.Core]
5 System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
6 // 代码大小 9 (0x9)
7 .maxstack 2
8 .locals init ([0] int32 CS$1$0000)
9 IL_0000: nop
10 IL_0001: ldarg.0
11 IL_0002: ldarg.1
12 IL_0003: add
13 IL_0004: stloc.0
14 IL_0005: br.s IL_0007
15 IL_0007: ldloc.0
16 IL_0008: ret
17 } // end of method ExpandInt::AddToOldNum
发现它和一般的静态方法没什么区别,唯一不同的是多了一行调用[System.Runtime.CompilerServices.ExtensionAttribute]:
custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
MSDN告诉我System.Runtime.CompilerServices.ExtensionAttribute表明一个法是一种可拓方法, 或一个类或集合包含扩展方法【这里我也不太懂,嘿嘿】。从这个类型的结尾Extension_Attribute_就可看出它是一个特性类。 为我们的AddToOldNum方法添加了必要的元数据。
再来看看Main方法里发生了什么情况:
1 .method public hidebysig static void Main() cil managed
2 {
3 .entrypoint
4 // 代码大小 19 (0x13)
5 .maxstack 2
6 .locals init ([0] int32 myNum)
7 IL_0000: nop
8 IL_0001: ldc.i4.1
9 IL_0002: stloc.0
10 IL_0003: ldloc.0
11 IL_0004: ldc.i4.1
12 IL_0005: call int32 ConsoleApplication1.ExpandInt::AddToOldNum(
13 int32, int32)
14 IL_000a: stloc.0
15 IL_000b: ldloc.0
16 IL_000c: call void [mscorlib]System.Console::WriteLine(int32)
17 IL_0011: nop
18 IL_0012: ret
19 } // end of method Program::Main
注意这一行,编译器把我们写的myNum = myNum.AddToOldNum(1)编译成这样:
IL_0005: call int32 ConsoleApplication1.ExpandInt::AddToOldNum(int32,int32)
"实例方法"的调用换成了ExpandInt::AddToOldNum(int32,int32)静态方法的调用,这就是扩展方法的本质所在了。
我们真的扩展了Int32类的实例方法了吗?没有,编译器帮我们披了一层外衣, 把对“实例方法”的调用在编译时期改变成了静态类中的静态方法的调用,所以扩展方法是一种编译时技术。当扩展方法和实例方法签名相同时,实例方法优先使用。