匿名方法的由来:
A。没有匿名方法的时候(C# 1.0)
addButton.Click += new EventHandler(AddClick);
void AddClick(object sender,EventArgs e)
{
listBox.Items.Add(textBox.Text);
}
B。有了匿名方法之后(C# 2.0)
addButton.Click += delegate
{
listBox.Items.Add(textBox.Text);
}; //最后要加分号
语法省略了方法名,因为一般情况下,在别的地方都不需要用到AddClick(包括方法名和原型)。
匿名方法简介:
匿名方法允许我们以一种“内联”的方式来编写方法代码,将代码直接与委托实例相关联,从而使得委托实例化的工作更加直观和方便。
匿名方法的几个相关问题:
A。匿名方法的参数:
匿名方法可以在delegate关键字后跟一个参数列表(可以不指定),后面的代码块则可以访问这些参数:
addButton.Click += delegate(object sender,EventArgs e){ MessageBox.Show(((Button)sender).Text); };
注意“不指定参数列表”与“参数列表为空”的区别。
addButton.Click += delegate { ... } //正确
addButton.Click += delegate() { ... } //错误
B。匿名方法的返回值:
如果委托类型的返回值类型为void,匿名方法里便不能返回任何值;
如果委托类型的返回值类型不为void,匿名方法里返回的值必须和委托类型的返回值兼容。
(1) delegate void MyDelegate();
MyDelegate d = delegate{ ... return; };
(2) delegate int MyDelegate();
MyDelegate d = delegate{ ... return 1; };
C。匿名方法的外部变量:
一些局部变量和参数有可能被匿名方法所使用,它们被称为“匿名方法的外部变量”。
外部变量的生存期会由于“匿名方法的捕获效益”而延长,一直延长到委托实例不被引用为止。
static void Foo(double factor)
{
Function f = delegate(int x)
{
factor += 0.2; //factor为外部变量,在匿名方法内部访问(外部变量被捕获)
return x*factor;
};
Invoke(f); //factor的生存期被延长
}
void Invoke(Fuction f)
{
for(int i=0;i<5;i++) f(i);
}
委托类型的推断:
C# 2.0允许我们在进行委托实例化时,省略掉委托类,而直接采用方法名,C#编译器会做合理的推断。
C# 1.0中的做法:
addButton.Click += new EventHandler(AddClick);
Apply(a,new Function(Math.Sin));
C# 2.0中的做法:
addButton.Click += AddClick;
Apply(a,Math.Sin);
匿名方法机制:
C# 2.0中的匿名方法仅仅是通过编译器的一层额外处理,来简化委托实例化的工作。它与C#1.0的代码不存在根本性的差别。
通过ILDsam.exe反汇编工具,可以获得对匿名方法的深入了解:
A。静态方法中的匿名方法
public delegate void D();
static void F()
{
D d = delegate { Console.WriteLine("test"); };
}
上面的代码被编译器转换为:
static void F()
{
D d = new D(MethodName); //MethodName代表编译器产生的名字
}
static void MethodName()
{
Console.WriteLine("test");
}
B。实例方法中的匿名方法
class Test
{
int x;
void F()
{
D d = delegate { Console.WriteLine(this.x); };
}
}
上面的代码被编译器转换为:
void F()
{
D d = new D(MethodName);
}
void MethodName()
{
Console.WriteLine(this.x);
}
C。匿名方法中的外部变量
void F()
{
int y = 123;
D d = delegate { Console.WriteLine(y); };
}
上面的代码被编译器转换为:
class ClassName
{
public int y;
public void MethodName()
{
Console.WriteLine(y);
}
}
void F()
{
ClassName t = new ClassName();
t.y = 123;
D d = new D(t.MethodName);
}
迭代器(省略)