pojia

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

匿名方法实现

编译器为匿名方法生成的代码很大程度上依赖于匿名方法使用的参数或变量的类型。例如,匿名方法使用其包含方法的局部变量(也叫做外部变量)还是使用类成员变量和方法参数?无论是哪一种情况,编译器都会生成不同的 MSIL。如果匿名方法不使用外部变量(也就是说,它只使用自己的参数或者类成员),则编译器会将一个私有方法添加到该类中,以便赋予方法一个唯一的名称。该方法的名称具有以下格式:

<return type> __AnonymousMethod$<random unique number>(<params>)

和其他编译器生成的成员一样,这都是会改变的,并且最有可能在最终版本发布之前改变。方法签名将成为它指派的委托的签名。

编译器只是简单地将匿名方法定义和赋值转换成推理委托类型的标准实例,以包装机器生成的私有方法:

SomeDelegate del = new SomeDelegate(__AnonymousMethod$00000000);

非常有趣的是,机器产生的私有方法并不显示在 IntelliSense 中,也不能显式地调用它,因为其名称中的美元符号对于 C# 方法来说是一个非法标记(但它是一个有效的 MSIL 标记)。

当匿名方法使用外部变量时,情况会更加困难。如果这样,编译器将用下面的格式添加具有唯一名称的私有嵌套类:

__LocalsDisplayClass$<random unique number>

嵌套类有一个名为 <this> 的指向包含类的引用,它是一个有效的 MSIL 成员变量名。嵌套类包含与匿名方法使用的每个外部变量对应的公共成员变量。编译器向嵌套类定义中添加一个具有唯一名称的公共方法,格式如下:

<return type> __AnonymousMethod$<random unique number>(<params>)

方法签名将成为被指派的委托的签名。编译器用代码替代匿名方法定义,此代码创建一个嵌套类的实例,并进行必要的从外部变量到该实例的成员变量的赋值。最后,编译器创建一个新的委托对象,以便包装嵌套类实例的公共方法,然后调用该委托来调用此方法。图 9 用 C# 伪代码展示了编译器为图 7 中定义的匿名方法生成的代码。

posted on 2008-03-27 20:14  破甲  阅读(281)  评论(0编辑  收藏  举报