CLR中匿名函数的实现原理浅析
http://tech.ddvip.com 2007年10月05日 社区交流
内容摘要:C# 2.0中提供了通过delegate实现匿名函数功能,能有效地减少用户的薄记代码工作
更方便的是编译器可以根据匿名函数使用的情况,自动判断函数参数,无需用户在定义时指定,如
以下为引用:
button1.Click+=delegate(Objectsender,EventArgse){MessageBox.Show("TheButtonwasclicked!");};
在不使用参数时,完全等价于
以下为引用:
button1.Click+=delegate{MessageBox.Show("TheButtonwasclicked!");};
相对于匿名函数的实现来说,比较复杂的是匿名函数对于其父作用域中变量的使用及其实现。MS的GrantRi在其blog上有一系列的讨论文章。
AnonymousMethods,Part1of?
AnonymousMethods,Part2of?
AnonymousMethodPart2answers
需要解决的问题有两个:一是不在一个变量作用域中的匿名函数如何访问父函数和类的变量;二是匿名函数使用到的变量的生命周期必须与其绑定,而不能与父函数的调用生命周期绑定。这两个问题使得C#编译器选择较为复杂的独立类封装方式实现匿名函数和相关变量生命周期的管理。
首先,匿名函数使用到的父函数中局部变量,无聊是引用类型还是值类型,都必须从栈变量转换为堆变量,以便在其作用域外的匿名函数实现代码可以访问并控制生命周期。因为栈变量的生命周期与其所有者函数是一致的,所有者函数退出后,其堆栈自动恢复到调用函数前,也就无法完成变量生命周期与函数调用生命周期的解耦。
例如下面这个简单的匿名函数中,使用了父函数的局部变量,虽然此匿名函数只在父函数里面使用,但C#编译器还是使用独立类对其使用到的变量进行了包装。
以下为引用:
delegatevoidDelegate1();
publicvoidMethod1()
{
inti=0;
Delegate1d1=delegate(){i++;};
d1();
}
责编:豆豆技术应用