我可不可以这样理解,性能只是在编译时有损失,编译之后就和普通的静态方法调用一样了,没有任何区别,之所以能得出这个结论是因为通过比较如下的两种调用方式和对应的IL代码:
class="brush:csharp;gutter:true;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Extention { class Program { static void Main(string[] args) { var dt = DateTime.Now; var dtString = dt.DT(); var dtString1 = Extention.Extention1.DT(dt); var dtString2 = Extention.Extention1.DT1(dt); Console.ReadLine(); } } public static class Extention1 { public static string DT(this DateTime dt) { return dt.ToString(); } public static string DT1(DateTime dt) { return dt.ToString(); } } }
Main函数中对DT的三种调用生成的IL代码如下:
C#编译器是如何快速的定位扩展方法的匹配的呢?
在C#中,一旦用this关键词标记了某个静态方法的第一个参数,编译器就会在内部向该方法应用一个定制特性ExtensionAttribute;
另外,任何静态类只要包含至少一个扩展方法,它的元数据也会应用这个特性,类似的,程序集中只要包含了至少一个符合上述特点的静态类,它的元数据中也会应用这个特性,
这样一来,如果代码调用了一个不存在的实例方法,编译器就能快速的扫描引用的所有程序集,判断他们哪些包含了扩展方法,然后在这些程序集中,可以只扫描包含了扩展方法的静态类,
在每个这样的静态类中,可以只扫描扩展方法来查找匹配,利用这些技术,代码能以最快的速度编译完毕;
.class public auto ansi abstract sealed beforefieldinit Extention.Extention1 extends [mscorlib]System.Object { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) // Methods .method public hidebysig static string DT ( valuetype [mscorlib]System.DateTime dt ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) // Method begins at RVA 0x2088 // Code size 19 (0x13) .maxstack 1 .locals init ( [0] string CS$1$0000 ) IL_0000: nop IL_0001: ldarga.s dt IL_0003: constrained. [mscorlib]System.DateTime IL_0009: callvirt instance string [mscorlib]System.Object::ToString() IL_000e: stloc.0 IL_000f: br.s IL_0011 IL_0011: ldloc.0 IL_0012: ret } // end of method Extention1::DT .method public hidebysig static string DT1 ( valuetype [mscorlib]System.DateTime dt ) cil managed { // Method begins at RVA 0x20a8 // Code size 19 (0x13) .maxstack 1 .locals init ( [0] string CS$1$0000 ) IL_0000: nop IL_0001: ldarga.s dt IL_0003: constrained. [mscorlib]System.DateTime IL_0009: callvirt instance string [mscorlib]System.Object::ToString() IL_000e: stloc.0 IL_000f: br.s IL_0011 IL_0011: ldloc.0 IL_0012: ret } // end of method Extention1::DT1 } // end of class Extention.Extention1Tencent\Users\378917466\QQ\WinTemp\RichOle\U9[MA_(7WQCKZSHKA{X`1LU.png" alt="" />