当然我们一定要看看它们背后卖的是什么药?
首先介绍一下扩展方法声明
扩展方法的行为和静态方法是非常类似的,你只能在静态类中声明它们。为声明一个扩展方法,你需要给该方法的第一个参数指定this关键字
例如:
首先定义一个汽车类,它具有Speed一个公共字段来提供它的速度
class Car
{
public int Speed;
public int SpeedUp()
{
return ++Speed;
}
}
接下来呢,我们为它提供一个静态类中的静态方法(多嘴一句,扩展方法只能定义在静态类的静态方法中).顺便也写上个一普通的静态方法来作比较{
public int Speed;
public int SpeedUp()
{
return ++Speed;
}
}
static class ExtensionMethodsClass
{
public static int SpeedDown(this Car c)
{
return --c.Speed;
}
public static void SpeedUp(Car car)
{
car.Speed++;
}
}
那我们就要测试一下我们的扩展方法了.{
public static int SpeedDown(this Car c)
{
return --c.Speed;
}
public static void SpeedUp(Car car)
{
car.Speed++;
}
}
static void Main(string[] args)
{
Car car = new Car();
car.SpeedUp();
Console.WriteLine(car.Speed.ToString());
car.SpeedDown();
Console.WriteLine(car.Speed.ToString());
ExtensionMethodsClass.SpeedUp(car);
Console.WriteLine(car.Speed.ToString());
Console.ReadLine();
}
编译,运行,接着看看结果,结果是什么并不重要,重要的就是我们要看看它们背后作了些什么.找出我们的法宝ildasm工具来,把你刚才的编译好的exe文件拽进去.{
Car car = new Car();
car.SpeedUp();
Console.WriteLine(car.Speed.ToString());
car.SpeedDown();
Console.WriteLine(car.Speed.ToString());
ExtensionMethodsClass.SpeedUp(car);
Console.WriteLine(car.Speed.ToString());
Console.ReadLine();
}
我们来比较着三个方法的il代码,看看里面到底发生了些什么!
首先呢看Car类中的SpeedUp()方法的il代码
1.method public hidebysig instance int32 SpeedUp() cil managed
2{
3 // Code size 23 (0x17)
4 .maxstack 3
5 .locals init ([0] int32 CS$1$0000,
6 [1] int32 CS$0$0001)
7 IL_0000: nop
8 IL_0001: ldarg.0
9 IL_0002: dup
10 IL_0003: ldfld int32 HelloLinq.Car::Speed
11 IL_0008: ldc.i4.1
12 IL_0009: add
13 IL_000a: dup
14 IL_000b: stloc.1
15 IL_000c: stfld int32 HelloLinq.Car::Speed
16 IL_0011: ldloc.1
17 IL_0012: stloc.0
18 IL_0013: br.s IL_0015
19 IL_0015: ldloc.0
20 IL_0016: ret
21} // end of method Car::SpeedUp
22
23
接着看ExtensionMethodsClass类中的SpeedDown()方法2{
3 // Code size 23 (0x17)
4 .maxstack 3
5 .locals init ([0] int32 CS$1$0000,
6 [1] int32 CS$0$0001)
7 IL_0000: nop
8 IL_0001: ldarg.0
9 IL_0002: dup
10 IL_0003: ldfld int32 HelloLinq.Car::Speed
11 IL_0008: ldc.i4.1
12 IL_0009: add
13 IL_000a: dup
14 IL_000b: stloc.1
15 IL_000c: stfld int32 HelloLinq.Car::Speed
16 IL_0011: ldloc.1
17 IL_0012: stloc.0
18 IL_0013: br.s IL_0015
19 IL_0015: ldloc.0
20 IL_0016: ret
21} // end of method Car::SpeedUp
22
23
1.method public hidebysig static int32 SpeedDown(class HelloLinq.Car c) cil managed
2{
3 .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
4 // Code size 23 (0x17)
5 .maxstack 3
6 .locals init ([0] int32 CS$1$0000,
7 [1] int32 CS$0$0001)
8 IL_0000: nop
9 IL_0001: ldarg.0
10 IL_0002: dup
11 IL_0003: ldfld int32 HelloLinq.Car::Speed
12 IL_0008: ldc.i4.1
13 IL_0009: sub
14 IL_000a: dup
15 IL_000b: stloc.1
16 IL_000c: stfld int32 HelloLinq.Car::Speed
17 IL_0011: ldloc.1
18 IL_0012: stloc.0
19 IL_0013: br.s IL_0015
20 IL_0015: ldloc.0
21 IL_0016: ret
22} // end of method ExtensionMethodsClass::SpeedDown
23
24
朋友们看累了吧,在忍一忍,看最后一个ExtensionMethodsClass类中的SpeedUp()方法2{
3 .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
4 // Code size 23 (0x17)
5 .maxstack 3
6 .locals init ([0] int32 CS$1$0000,
7 [1] int32 CS$0$0001)
8 IL_0000: nop
9 IL_0001: ldarg.0
10 IL_0002: dup
11 IL_0003: ldfld int32 HelloLinq.Car::Speed
12 IL_0008: ldc.i4.1
13 IL_0009: sub
14 IL_000a: dup
15 IL_000b: stloc.1
16 IL_000c: stfld int32 HelloLinq.Car::Speed
17 IL_0011: ldloc.1
18 IL_0012: stloc.0
19 IL_0013: br.s IL_0015
20 IL_0015: ldloc.0
21 IL_0016: ret
22} // end of method ExtensionMethodsClass::SpeedDown
23
24
1.method public hidebysig static void SpeedUp(class HelloLinq.Car car) cil managed
2{
3 // Code size 16 (0x10)
4 .maxstack 8
5 IL_0000: nop
6 IL_0001: ldarg.0
7 IL_0002: dup
8 IL_0003: ldfld int32 HelloLinq.Car::Speed
9 IL_0008: ldc.i4.1
10 IL_0009: add
11 IL_000a: stfld int32 HelloLinq.Car::Speed
12 IL_000f: ret
13} // end of method ExtensionMethodsClass::SpeedUp
14
15
2{
3 // Code size 16 (0x10)
4 .maxstack 8
5 IL_0000: nop
6 IL_0001: ldarg.0
7 IL_0002: dup
8 IL_0003: ldfld int32 HelloLinq.Car::Speed
9 IL_0008: ldc.i4.1
10 IL_0009: add
11 IL_000a: stfld int32 HelloLinq.Car::Speed
12 IL_000f: ret
13} // end of method ExtensionMethodsClass::SpeedUp
14
15
朋友们,看到了这其中的奥秘了吧,第一个方法就是一个普通的实例方法,第三个方法呢就是一个普通的静态方法,这最特别的就是我们的第二个了,也就是我们的扩展方法,它特别在
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
这句话翻译成普通话的意思就是告诉编译器我这个方法只能用在实例方法上,具体那个实例呢,由入口参数来决定的.这个特性不错吧,一个字好.但是在好也不能滥用,就像医院治病打强心针似的,好,的确治病.但是不能因为能治病就给每一个病人都打.滥用是错误地,就像这打强心针一样不到非用不可的地步我认为还是不用为好,很容易就被滥用.那这么说吧,你找到用这个东西的合适的理由那你就放心的用吧!