zoukankan      html  css  js  c++  java
  • [C#3] 1扩展方法

    1.从DEMO开始

    先看一个扩展方法的例子:

     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代码层面来看看吧。

    2.扩展方法剖析

    这里是上面代码编译的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)静态方法的调用,这就是扩展方法的本质所在了。

    3.总结

    我们真的扩展了Int32类的实例方法了吗?没有,编译器帮我们披了一层外衣, 把对“实例方法”的调用在编译时期改变成了静态类中的静态方法的调用,所以扩展方法是一种编译时技术。当扩展方法和实例方法签名相同时,实例方法优先使用。

  • 相关阅读:
    开发环境之Webpack
    开发环境之Nginx
    Winfrom排坑
    Winfrom打包教程(Inno Setup工具)
    博客园美化教程
    开发环境之Tomcat
    IDEA编码时卡顿问题
    学习Spring5源码时所遇到的坑
    docker+jmeter+influx+granfana搭建性能测试监控平台
    Windows10上安装 WSL---Ubuntu
  • 原文地址:https://www.cnblogs.com/linianhui/p/csharp3_extension_method.html
Copyright © 2011-2022 走看看