[C#3] 1-扩展方法

简介: 1.从DEMO开始 先看一个扩展方法的例子: 1 class Program 2 { 3 public static void Main() 4 { 5 Int32 myNum = 1; 6 myNum = myNum.

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

作者: Blackheart
目录
相关文章
|
7月前
|
算法 C#
C#开源实用的工具类库,集成超过1000多种扩展方法
C#开源实用的工具类库,集成超过1000多种扩展方法
|
C# 开发者
C#扩展方法和工具类的区别
扩展方法和工具类的主要区别在于它们的作用。扩展方法旨在扩展现有的类,而工具类旨在提供一组通用且可靠的方法来执行某些任务。当需要扩展现有的类时,使用扩展方法;当需要实用函数来执行通用任务时,使用工具类。
93 0
|
编译器 C#
c# 自定义扩展方法
c# 自定义扩展方法
|
C#
c#中的扩展方法
c#中的扩展方法
101 0
C# 扩展方法 白话总结
我们在变成的时候时常遇到这样的问题,new了一个系统内的对象之后,我们想要对该对象有一个方法可是却点不出来,说明该对象本身没有声明该方法,可是微软又不允许我们去该对象的代码,怎么办? 在C# 3.
914 0