扩展方法到底做了什么
2010-05-26 18:41
281 查看
扩展方法是.net3.5以后出现的一个比较优雅的写法,昨天讨论中有同学提出这也是通过反射实现的,不过我并不这么认为。
扩展方法的定义必须是静态类的静态方法,对一个静态类的静态方法进行反射明显不明智。而且linq to object中大量使用扩展方法,如果是用发射实现方法调用,明显过于笨拙。
那么事实到底如何
先定义一个扩展方法和一个同样功能的非扩展方法
IL代码
IL_0000: nop
IL_0001: ldstr "hello world!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.5
IL_0009: ldstr "..."
IL_000e: call string [StringHelp]StringHelp.StringHelp::CutStr(string,
int32,
string)
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: nop
IL_0019: ldloc.0
IL_001a: ldc.i4.5
IL_001b: ldstr "..."
IL_0020: call string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
int32,
string)
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: ldtoken [StringHelp]StringHelp.StringHelp
IL_0030: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0035: ldstr "CutStr"
IL_003a: call instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string)
IL_003f: ldnull
IL_0040: ldc.i4.3
IL_0041: newarr [mscorlib]System.Object
IL_0046: stloc.1
IL_0047: ldloc.1
IL_0048: ldc.i4.0
IL_0049: ldloc.0
IL_004a: stelem.ref
IL_004b: ldloc.1
IL_004c: ldc.i4.1
IL_004d: ldc.i4.5
IL_004e: box [mscorlib]System.Int32
IL_0053: stelem.ref
IL_0054: ldloc.1
IL_0055: ldc.i4.2
IL_0056: ldstr "..."
IL_005b: stelem.ref
IL_005c: ldloc.1
IL_005d: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object,
object[])
IL_0062: call void [mscorlib]System.Console::WriteLine(object)
三种调用的方式是这样的:
1、string [StringHelp]StringHelp.StringHelp::CutStr(string, int32, string)
2、string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
int32,
string)
3、instance object [mscorlib]System.Reflection.MethodBase::Invoke(object,
object[])
很明显,并没有使用反射,而是编译器的语法糖,使得调用方法更为简便。在编译时期,编译器会对代码作用域范围内可见的所有静态类,且带this 特征参数的方法进行搜索,
然后透明调用符合特征的方法。
那么效率如何呢
![](http://images.cnblogs.com/cnblogs_com/brightwang/157801/o_diaoyong.jpg)
1、86 2、84 3、313
效率基本没有,差别,因为其实调用的方式都没有什么区别,而且性能比反射自然要好很多。
扩展方法的定义必须是静态类的静态方法,对一个静态类的静态方法进行反射明显不明智。而且linq to object中大量使用扩展方法,如果是用发射实现方法调用,明显过于笨拙。
那么事实到底如何
先定义一个扩展方法和一个同样功能的非扩展方法
IL代码
IL_0000: nop
IL_0001: ldstr "hello world!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.5
IL_0009: ldstr "..."
IL_000e: call string [StringHelp]StringHelp.StringHelp::CutStr(string,
int32,
string)
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: nop
IL_0019: ldloc.0
IL_001a: ldc.i4.5
IL_001b: ldstr "..."
IL_0020: call string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
int32,
string)
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: ldtoken [StringHelp]StringHelp.StringHelp
IL_0030: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0035: ldstr "CutStr"
IL_003a: call instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string)
IL_003f: ldnull
IL_0040: ldc.i4.3
IL_0041: newarr [mscorlib]System.Object
IL_0046: stloc.1
IL_0047: ldloc.1
IL_0048: ldc.i4.0
IL_0049: ldloc.0
IL_004a: stelem.ref
IL_004b: ldloc.1
IL_004c: ldc.i4.1
IL_004d: ldc.i4.5
IL_004e: box [mscorlib]System.Int32
IL_0053: stelem.ref
IL_0054: ldloc.1
IL_0055: ldc.i4.2
IL_0056: ldstr "..."
IL_005b: stelem.ref
IL_005c: ldloc.1
IL_005d: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object,
object[])
IL_0062: call void [mscorlib]System.Console::WriteLine(object)
三种调用的方式是这样的:
1、string [StringHelp]StringHelp.StringHelp::CutStr(string, int32, string)
2、string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
int32,
string)
3、instance object [mscorlib]System.Reflection.MethodBase::Invoke(object,
object[])
很明显,并没有使用反射,而是编译器的语法糖,使得调用方法更为简便。在编译时期,编译器会对代码作用域范围内可见的所有静态类,且带this 特征参数的方法进行搜索,
然后透明调用符合特征的方法。
那么效率如何呢
![](http://images.cnblogs.com/cnblogs_com/brightwang/157801/o_diaoyong.jpg)
1、86 2、84 3、313
效率基本没有,差别,因为其实调用的方式都没有什么区别,而且性能比反射自然要好很多。
相关文章推荐
- Activity中的setContentView方法到底做了什么?
- C#3.0 为我们带来什么(6) —— 扩展方法
- web到底是什么意思,web站点的创建方法
- C#中引用类型做方法参数时,加ref或out,与不加ref或out到底有什么区别?
- getUserPrincipal() 这个方法到底是做什么用的?
- 来说一说chrome扩展和chrome插件到底有什么区别?
- 错例:做类扩展时不调用父类方法 会发生什么?
- 扩展方法为我们带来了什么
- 这些集成方法到底有什么不一样
- java中 static变量和方法到底是存在内存什么区域呢?
- 什么是扩展方法 (Extension Methods)?
- Linq入门——什么是linq & 扩展方法
- 敏捷(Agile)工作方法到底能帮你解决什么问题
- 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
- 什么是扩展方法
- equals方法与==到底有什么区别
- Linq入门——什么是linq & 扩展方法
- 委托是什么?匿名方法是什么?在C# 3.0中,Lambda表达式是什么?扩展方法是什么?LINQ是什么?您觉得C# 3.0中还有哪些重要的特性,它们带来了什么优势?BCL中哪些类库和这些特性有关?您平时最常用哪些
- session.flush方法到底干了一些什么事情,举一个具体的例子说明
- java中 static变量和方法到底是存在内存什么区域?