1、委托
委托类似与C++语言中的函数指针,委托可以指向方法的引用。从数据类型来说,委托和类一样,是一种自定义数据类型。
1.1 委托的声明
使用delegate关键字声明委托类型:
访问限定符 delegate 返回值类型 函数名(参数类型 参数名, ...);
public delegate void MyDel(int x);
1.2 委托的实例化
实例化委托需要一个与委托类型签名完全匹配的方法,方法的返回值、参数类型以及参数个数必须与委托类型完全一致。
public delegate void MyDel(string text);
public class Sample
{
public void Put(string text)
{
Console.WriteLine(text);
}
}
public static void Add(string text)
{
... ...
}
static void Main()
{
Sample sample = new Sample();
MyDel mydel1 = sample.Put;——将实例方法赋值给委托
MyDel mydel2 = Add;——将静态方法赋值给委托
mydel1("Hello World");
}
1.3 委托作为参数传递
public delegate bool ComparisonHander(int first, int second);
class DelegateSample
{
public static void BubbleSort(ComparisonHandler comparMethod) //使用委托作为形参
{
... ...
}
public static bool GreaterThan(int first, int second)
{
return first < second;
}
static void Main()
{
BubbleSort(GreaterThan); //将方法作为实参传递
}
}
1.4 委托的内部机制
委托实际是特殊的类。在.NET中,委托类型是从System.MulticastDelegate派生的,而后者又从System.Delegate派生。System.Delegate中包含一个MethodInfo类型参数,用于描述方法的名称、参数和返回类型。以及一个Object类型参数,用于指定一个对象的实例,起到Target的作用。
虽然委托是间接的从System.Delegate派生,但是,C#不允许任何声明直接或间接从System.Delegate或System.MulticaseDelegate派生的类。
委托是不可变的,一旦创建则无法更改。如果变量包含了委托的引用,还想引用其他不同的方法,则必须创建一个新的委托。
2、Lambda表达式
想要使用委托需要声明委托、定义委托方法、声明委托变量并将委托方法赋值给委托变量三个步骤。为了进一步精简语法,C#2.0引入了匿名方法,C#3.0又对匿名方法进一步精简,称为Lambda表达式。Lambda表达式允许直接将代码块赋值给委托变量,也支持作为形参传递给委托变量。
BubbleSort(items, (first, second) =>
{
return first < second'
});
2.1 Lambda表达式的内部机制
Lamdba表达式就是一个更精简的委托方法,因为返回值类型、参数类型都可以通过委托得到,所以可以省略不写,只要参数个数相同即可。
当编译器遇到Lambda表达式时,会将它转换为特殊的隐藏类、字段和方法,也就是编译器自动生成委托的相关代码,而不用程序员自己编写。
2.2 外部变量
在Lambda表达式外部声明的局部变量称为外部变量。局部变量的生存周期一般与它的作用域绑定,一旦控制离开作用域,则变量不再生效。但如果Lambda表达式捕捉了外部变量,就必须保证外部变量能够安全的访问,因此被捕获的外部变量的生命周期将被延长。具体由C#编译器负责生成CIL代码。