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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一枝花算不算浪漫

[读书笔记]C#学习笔记五: C#3.0自动属性,匿名属性及扩展方法

35510
来自专栏静晴轩

类数组借用数组方法

于JavaScript如何将对象转化为数组对象,其用法写法已经很常见且完善,比如JQuery中的makeArray函数对此的实现,也是跟大家想的差不多,只是考虑...

3569
来自专栏xx_Cc的学习总结专栏

iOS-正则表达式的简单使用

4437
来自专栏web前端教室

不学不知道,sort()方法中的坑

今天的前端零基础课,在讲到js中的sort()排序方法的时候,说sort()这个方法在给数字排序的时候,根本不是按数字大小来排序的。 它是把数字都当成字符串来看...

19210
来自专栏Kiba518

C#语法——泛型的多种应用

泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性、类型安全性和效率。

943
来自专栏互联网开发者交流社区

Java逻辑

1514
来自专栏hbbliyong

看到他我一下子就悟了-- 泛型(1)

1.泛型概念:       本质上,术语”泛型”指的是”参数化类型(parameterized types)”.参数化类型非常重要,因为它们可以在创建类.结构....

2875
来自专栏软件开发

JavaSE学习总结(八)—— 异常处理(Exception)

一、理解异常及异常处理的概念 异常就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。 异常不是错误 程序中关键的位置有异常处理,提高程序的稳定...

2339
来自专栏陈仁松博客

C# 7.0 探索之旅

模式匹配(Pattern matching) C# 7.0 引入了模式匹配的概念,一种从抽象的角度来说,指可以测试一个值是否有某种特定的“形状”、并在满足这一条...

4799
来自专栏web前端-

JavaScript运算符和控制语句

语法: switch(n)  {      case 1:      执行代码块 1      break;      case 2:      执行代码块 2...

872

扫码关注云+社区

领取腾讯云代金券