方法组转换

前面的文章介绍过,C# 1.0中出现委托这个核心概念,在C# 2.0中,委托得到了很大的改进。C# 2.0中委托的改进为C# 3.0中的新特性提供了铺垫,当我们了解了匿名方法后,Lambda的学习就会变得相对容易。

下面就看看C# 2.0中委托的改进。

方法组转换

在C# 1.0中,如果要创建一个委托实例,就必须同时指定委托类型和符合委托签名的方法。但是,在C# 2.0中,支持了方法组转换,也就是说我们可以从方法组到一个兼容委托类型的隐式转换。所谓"方法组"(method group),其实就是一个方法名。

看一个例子:

class Program { public delegate void ReverseStringHandler(string str); private static void ReverseString(string str) { char[] charArray = str.ToCharArray(); Array.Reverse(charArray); Console.WriteLine(charArray); } static void Main(string[] args) { //C# 1.0中创建委托实例 ReverseStringHandler reverseStringHandler = new ReverseStringHandler(ReverseString); reverseStringHandler("Hello World"); //C# 2.0中通过方法组转换创建委托实例 reverseStringHandler = ReverseString; reverseStringHandler("Good morning"); } }

通过方法组转换,繁琐的委托实例创建得到了简化。

匿名方法

根据C# 1.0中了解到的知识,当我们创建一个委托实例的时候,我们需要找到一个跟委托类型签名一致的方法,用这个方法来实例化一个委托对象。

看看前面的字符串反转的例子,可能"ReverseString"这个方法在程序中只会使用一次,但是为了创建委托实例,这个方法必须要存在。

在C# 2.0中引入了匿名方法,所以有了更简单的方式实现上面的例子:

public delegate void ReverseStringHandler(string str); static void Main(string[] args) { ReverseStringHandler reverseStringHandler = delegate(string str) { char[] charArray = str.ToCharArray(); Array.Reverse(charArray); Console.WriteLine(charArray); }; reverseStringHandler("Hello World"); Console.Read(); }

从上面可以看到,匿名方法就是通过delegate关键字以及参数列表和具体语句块的实现。

所以说,如果用来实例化委托的方法比较简单,并且这个方法在其他地方使用的频率很低时,这时候就可以考虑用匿名方法来进行简化。

匿名方法工作原理

如果你对匿名方法仍有疑惑,建议你看看上面例子的IL代码。

在Main函数的IL代码中,可以看到编译器为我们生成了一个名为"<Main>b__0"的方法,方法接受一个string类型的参数。

.method private hidebysig static void Main ( string[] args ) cil managed { …… IL_0009: ldftn void AnonymousMethod.Program::'<Main>b__0'(string) …… } // end of method Program::Main

当我们查看"<Main>b__0"方法的IL代码后,可以看到这个方法就是我们在匿名方法的语句块中定义的操作。

.method private hidebysig static void '<Main>b__0' ( string str ) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Method begins at RVA 0x2050 // Code size 23 (0x17) .maxstack 1 .locals init ( [0] char[] charArray ) IL_0000: nop IL_0001: ldarg.0 IL_0002: callvirt instance char[] [mscorlib]System.String::ToCharArray() IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: call void [mscorlib]System.Array::Reverse(class [mscorlib]System.Array) IL_000e: nop IL_000f: ldloc.0 IL_0010: call void [mscorlib]System.Console::WriteLine(char[]) IL_0015: nop IL_0016: ret } // end of method Program::'<Main>b__0'

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/1da3117f8f8f443cc648cd013e28f4b4.html