.NET3.5 发展的背后(2)--扩展方法
2008-03-02 17:48 Franz 阅读(426) 评论(0) 收藏 举报
今天我接着给大家演绎一下.net3.5的新特性.那就是扩展方法(extention method),这个也是比较有意思的.你可以使用实例方法的语法来调用静态方法,你可以不把要扩展的方法加到代码里就可以对这个类进行扩展,这个对买别人dll用的,或者说是相对某编译好的类在扩展一下提供了可能.
当然我们一定要看看它们背后卖的是什么药?
首先介绍一下扩展方法声明
扩展方法的行为和静态方法是非常类似的,你只能在静态类中声明它们。为声明一个扩展方法,你需要给该方法的第一个参数指定this关键字
例如:
首先定义一个汽车类,它具有Speed一个公共字段来提供它的速度
class Car
{
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++;
}
}
那我们就要测试一下我们的扩展方法了.
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文件拽进去.
我们来比较着三个方法的il代码,看看里面到底发生了些什么!
首先呢看Car类中的SpeedUp()方法的il代码
朋友们,看到了这其中的奥秘了吧,第一个方法就是一个普通的实例方法,第三个方法呢就是一个普通的静态方法,这最特别的就是我们的第二个了,也就是我们的扩展方法,它特别在
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
这句话翻译成普通话的意思就是告诉编译器我这个方法只能用在实例方法上,具体那个实例呢,由入口参数来决定的.
这个特性不错吧,一个字好.但是在好也不能滥用,就像医院治病打强心针似的,好,的确治病.但是不能因为能治病就给每一个病人都打.滥用是错误地,就像这打强心针一样不到非用不可的地步我认为还是不用为好,很容易就被滥用.那这么说吧,你找到用这个东西的合适的理由那你就放心的用吧!
当然我们一定要看看它们背后卖的是什么药?
首先介绍一下扩展方法声明
扩展方法的行为和静态方法是非常类似的,你只能在静态类中声明它们。为声明一个扩展方法,你需要给该方法的第一个参数指定this关键字
例如:
首先定义一个汽车类,它具有Speed一个公共字段来提供它的速度
class Car
{
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++;
}
}
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();
}我们来比较着三个方法的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()方法
.method public hidebysig instance int32 SpeedUp() cil managed2
{3
// Code size 23 (0x17)4
.maxstack 35
.locals init ([0] int32 CS$1$0000,6
[1] int32 CS$0$0001)7
IL_0000: nop8
IL_0001: ldarg.09
IL_0002: dup10
IL_0003: ldfld int32 HelloLinq.Car::Speed11
IL_0008: ldc.i4.112
IL_0009: add13
IL_000a: dup14
IL_000b: stloc.115
IL_000c: stfld int32 HelloLinq.Car::Speed16
IL_0011: ldloc.117
IL_0012: stloc.018
IL_0013: br.s IL_001519
IL_0015: ldloc.020
IL_0016: ret21
} // end of method Car::SpeedUp22

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()方法
.method public hidebysig static int32 SpeedDown(class HelloLinq.Car c) cil managed2
{3
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) 4
// Code size 23 (0x17)5
.maxstack 36
.locals init ([0] int32 CS$1$0000,7
[1] int32 CS$0$0001)8
IL_0000: nop9
IL_0001: ldarg.010
IL_0002: dup11
IL_0003: ldfld int32 HelloLinq.Car::Speed12
IL_0008: ldc.i4.113
IL_0009: sub14
IL_000a: dup15
IL_000b: stloc.116
IL_000c: stfld int32 HelloLinq.Car::Speed17
IL_0011: ldloc.118
IL_0012: stloc.019
IL_0013: br.s IL_001520
IL_0015: ldloc.021
IL_0016: ret22
} // end of method ExtensionMethodsClass::SpeedDown23

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![]()
.method public hidebysig static void SpeedUp(class HelloLinq.Car car) cil managed2
{3
// Code size 16 (0x10)4
.maxstack 85
IL_0000: nop6
IL_0001: ldarg.07
IL_0002: dup8
IL_0003: ldfld int32 HelloLinq.Car::Speed9
IL_0008: ldc.i4.110
IL_0009: add11
IL_000a: stfld int32 HelloLinq.Car::Speed12
IL_000f: ret13
} // end of method ExtensionMethodsClass::SpeedUp14

15

朋友们,看到了这其中的奥秘了吧,第一个方法就是一个普通的实例方法,第三个方法呢就是一个普通的静态方法,这最特别的就是我们的第二个了,也就是我们的扩展方法,它特别在
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )这个特性不错吧,一个字好.但是在好也不能滥用,就像医院治病打强心针似的,好,的确治病.但是不能因为能治病就给每一个病人都打.滥用是错误地,就像这打强心针一样不到非用不可的地步我认为还是不用为好,很容易就被滥用.那这么说吧,你找到用这个东西的合适的理由那你就放心的用吧!

浙公网安备 33010602011771号