一、匿名方法:
引入背景:
C#引入匿名方法是为了简化代理函数(delegate method)定义。
关于anonymous method的语法参考官网。
留心容易被忽略的地方:
1. 匿名方法不能访问外部方法的ref和out参数。
Why?!
不安全
2. 匿名方法内的局部变量不可以与外部方法的局部变量重名,否则编译会报重定义错误。
Why? !
C#的作用域最小单元是方法作用域,所以方法内的所有变量是不能重名的。虽然匿名方法也是一种“方法”,但是他被定义在方法内,所以应该也遵循最小作用域的原则。
像for,do-While等语句也遵循这个原则。匿名方法内的局部变量可以与外部类的成员变量同名(作用域不同啊,当然可以了^_^)。
3. 匿名方法可以访问外部方法定义的局部变量,也可以访问外部类成员方法和成员变量(即使是访问权限是Private的成员)。
这会使得所引用的外部变量或者外部类的成员变量生命周期变长。
3-1: 匿名方法引用外部方法局部变量:
class MyAnonymous
{
public Func<int> ReturnFun()
{
int result = -1;
return delegate
{
return result;
};
}
static void Main(string[] args)
{
MyAnonymous a = new MyAnonymous();
Func<int> f = a.ReturnFun();
Console.WriteLine(f());
}
}
结果输出:-1
按理说方法ReturnFun执行完后,其内部的局部变量result的生命周期就完了,但是由于匿名方法类引用了该局部变量,所以局部变量result的生命周期并没有结束,而是被延长了直到指向其所在的匿名方法的delegate生命周期结束。
3-2:匿名方法引用外部类成员:
类似3-1。
总体说如果匿名方法引用了外部变量(外部方法的局部变量或者外部类成员)就好比增量一个访问外部变量的方式(通过匿名方法)。
二、Lambda表达式
引入背景:
更方便的书写匿名表达式,他的引入就是为了简化匿名方法的书写。所以在使用到匿名方法的地方,以及对匿名方法的规则同样适用于Lambda表达式。
但是!!!!官网上说两者还是有点区别的:“有一种情况下,匿名方法提供了 Lambda 表达式中所没有的功能。您可使用匿名方法来忽略参数列表。 这意味着匿名方法可转换为具有各种签名的委托。 这对于 Lambda 表达式来说是不可能的”。简单的来讲就是匿名方法可以省略形参,而Lambda表达式不可以省略。
举例说明:
Func<int, int> func = delegate(int p)
{
return 1990;
};
这个表达式可以省略形参简写为:
Func<int, int> func = delegate //注意这个地方省略的形参。
{
return 1990;
};
而对于Lambda表达式来说不能省略形参,必须显示的指明形参:
Func<int, int> func = i => 1990;
不能简写成:
Func<int, int> func = () => 1990;