匿名方法和Lambda表达式
匿名方法和Lambda表达式
1、匿名方法
在C#2.0版本中引入了匿名方法,匿名方法与具名方法(即普通的方法)相对
简单示例:
delegate void MyDelegate(int x); //声明一个委托类型
void Main()
{
MyDelegate del = delegate(int x)
{
Console.WriteLine($"匿名方法输出值:{x}");
};
del(20);
}
使用场景
- 给初始化委托变量
- 给组合委托赋值
- 给委托增加方法
语法
匿名方法必须与关联的委托保持格式一致,也就是返回值和参数需要相同,注意语句块后面是有分号的,不要漏掉
delegate(参数列表) {语句块};
返回值
匿名方法不会显示地声明返回值,但是返回值要和对应的委托保持一致。如果委托没有返回值,即为void时,匿名方法则不能有返回值;如果委托有返回值,则匿名函数需要在语句块中返回对应类型的值。
delegate int MyDelegate(int x); //声明一个委托类型
void Main()
{
MyDelegate del = delegate(int x)
{
Console.WriteLine($"匿名方法输出值:{x}");
return (x + 10);
};
}
参数列表
参数列表要和声明的委托保持一致,也就是参数的个数、类型及位置。
当委托没有out参数或匿名方法没有输入参数时,则可以省略匿名方法的参数列表。当匿名方法不需要输入参数时,这种情况下参数列表可以和委托不一致了,但同时在调用委托时,传入的参数也不会起到作用。
delegate int MyDelegate(int x); //声明一个委托类型
void Main()
{
MyDelegate del = delegate
{
Console.WriteLine($"匿名方法不需要使用输入参数");
return 10;
};
del(20);
}
如果在委托类型的声明中,参数列表使用了params参数,则匿名方法的参数列表会忽略params关键字的作用。
外部变量的捕获
在匿名方法中使用方法块外部的变量很简单,可以直接使用
delegate int MyDelegate(int x); //声明一个委托类型
void Main()
{
int val = 20;
MyDelegate del = delegate
{
//捕获匿名方法外部的val变量
Console.WriteLine($"匿名方法输出:{val+10}");
return 10;
};
del(20);
}
输出:
匿名方法输出:30
捕获变量的生命周期会在委托被调用时得到扩展
MyDelegate del;
{
int val = 20; //val变量的作用域和生命周期在此代码块中
del = delegate
{
Console.WriteLine($"匿名方法输出:{val + 10}");
return 10;
};
}
del(20); //委托调用时,由于匿名方法捕获了val变量,val变量的生命周期在此得到延续
2、Lambda表达式
在C#3.0中引入Lambda,简化了匿名方法,用来替代匿名方法。lambda表达式相比匿名方法,不需要使用delegate关键字,并且有更精简的写法,易于理解也提高了效率。
使用场景
和匿名方法一样,作为委托delegate的初始化方法或给委托增加方法
还可以用在属性的get、set中
语法格式
Lambda运算符=>,读作 goes to
参数列表 => 方法块
示例:
delegate void MyDelegate(int x); //声明一个委托类型
void Main()
{
MyDelegate del;
del = delegate (int x) { Console.WriteLine($"匿名方法输出:{x}"); }; //匿名方法
del = (int x) => { Console.WriteLine($"Lambda表达式输出:{x}"); }; //lambda表达式
del(20);
}
带返回值
delegate int MyDelegate1(int x); //声明一个委托类型
void Main()
{
MyDelegate1 del1;
del1 = x =>
{
Console.WriteLine($"Lambda表达式输出:{x}");
return 10;
};
del1(100);
}
参数列表
- 参数列表一般来说格式要和委托类型保持一致
- 没有参数时,必须要用空的()来表示
- 只有一个参数时,可以省略()
- Lambda表达式中参数类型可以省略,除非委托参数中有ref和out修饰的参数,则不可省略
参数列表带有类型称为显示类型,没有类型称为隐式类型
delegate void MyDelegate(int x); //声明一个委托类型
void Main()
{
MyDelegate del;
del = (int x) => { Console.WriteLine($"Lambda表达式输出:{x}"); };
del = (x) => { Console.WriteLine($"Lambda表达式输出:{x}"); }; //省略类型
del = x => { Console.WriteLine($"Lambda表达式输出:{x}"); }; //省略()
del = x => Console.WriteLine($"Lambda表达式输出:{x}"); //只有一条语句,也可以放return的表达式
del(20);
}
多个参数
delegate int MyDelegate2(int x, int y, int z); //声明一个委托类型
void Main()
{
MyDelegate2 del2, del3, del4;
del2 = (int x, int y, int z) =>
{
Console.WriteLine($"x = {x}, y = {y}, z = {z}");
return 20;
};
del3 = (x, y, z) => x + y + z; //省略参数类型,一个语句作为return表达式
//del4 = x, y, z => x + y + z; //多个参数时无法省略()
del2(3, 5, 7);
Console.WriteLine(del3(3, 5, 7));
}
输出
x = 3, y = 5, z = 7
15