C#中Lambda表达式的用法

作者:Ruby_Lu 时间:2022-07-29 17:29:56 

从C#3.0开始,可以使用lambda表达式把实现代码赋予委托。lambda表达式与委托(https://www.jb51.net/article/244051.htm)直接相关。当参数是委托类型时,就可以使用lambda表达式实现委托引用。

static void Main()
       {
             string mid = ", middle part,";

Func<string, string> anonDel =  param =>
             {
               param += mid;
               param += " and this was added to the string.";
               return param;
             };
             Console.WriteLine(anonDel("Start of string"));

}

lambda运算符&ldquo;=>&rdquo; 的左边是参数列表,右边是lambda变量的方法的实现代码。

1.参数

如果lambda表达式只有一个参数,只写出参数名就可以,像上面的代码。
如果委托使用多个参数,就需要把参数名放到括号中:

Func<double, double, double> twoParams = (x, y) => x * y;
Console.WriteLine(twoParams(3, 2));

可以在括号中给变量名添加参数类型:

Func<double, double, double> twoParamsWithTypes = (double x, double y) => x * y;
Console.WriteLine(twoParamsWithTypes(4, 2));

2.多行代码

如果lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐形的return语句。

Func<double, double, double> twoParams = (x, y) => x * y;

Func<double, double, double> twoParams = (x, y) =>

retrun x * y;
}

如果在lambda表达式的实现代码中有多条语句,就必须添加花括号和return语句:

Func<string, string> anonDel = param =>
{
param += mid;
param += " and this was added to the string.";
return param;
};

3.闭包

通过lambda表达式可以访问lambda表达式块外部的变量,这称为闭包。闭包是一个很好的功能,但如果使用不当,会很危险。例如:

int someVal = 5;
Func<int,int> f = x => x+someVal;

假定以后修改了变量someVal,于是调用委托f时,会使用someVa的新值:

someVal = 7;
f(3);//结果为10而不是8.

特别是,通过另一个线程调用lambda表达式时,我们可能不知道进行了这个调用,也不知道外部变量的当前值是什么。
所以在使用闭包时,一定要谨慎!!!
在lambda表达式访问lambda表达式块外部的变量时,编译器在定义lambda表达式时,编译器会创建一个匿名类,它用一个构造函数来传递外部变量。该构造函数取决于从外部传递进来的变量个数和类型。
对于lambda表达式Func<int,int> f = x => x+someVal;

public class AnonymousClass
       {
           private int someVal;
           public AnonymousClass(int someVal)
           {
               this.someVal = someVal;
           }

public int AnonymousMethod(int x)
           {
               retrun x+someVal;
           }
       }

使用lambda表达式并调用该方法的时,会创建匿名类的一个实例,并传递调用该方法时变量的值。

4.使用foreach语句的闭包

先看下面这个例子:

var values = new List<int>() {10,20,30};
var funcs = new List<Func<int>>();

foreach(var val in values)
{
funcs.Add(() => val);
}

foreach(var f in funcs)
{
Console.WriteLine((f()));
}

第一条foreach语句添加了funcs列表中每个元素。添加到列表中的函数使用lambda表达式。该lambda表达式使用了一个变量val,该变量在lambda表达式的外部定义为foreach语句的循环变量。第二条foreach语句迭代funcs列表,以调用列表中引用的每个函数。
在C#5.0之前版本编译这段代码时,会在控制台输出30三次。这是因为,在第一个foreach循环中使用闭包,所创建的函数是在调用时,而不是在迭代时获得val变量的值。在https://www.jb51.net/article/244045.htm中介绍foreach时讲到编译器会从foreach语句中创建一个while循环。在C#5.0之前版本中,编译器在while循环外部定义循环变量,在每次迭代中重用这个变量。因此,在循环结束时,该变量的值就是最后一次迭代时的值。要想在使用C#5.0之前版本时,输出10,20,30,需要将代码改为使用一个局部变量:

var values = new List<int>() {10,20,30};
var funcs = new List<Func<int>>();

foreach(var val in values)
{
var v = val;
funcs.Add(() => v);
}

foreach(var f in funcs)
{
Console.WriteLine((f()));
}

在C#5.0中,不再需要做这种代码修改。C#5.0会在while循环的代码中创建一个不同的局部循环变量。

来源:https://www.cnblogs.com/afei-24/p/6795233.html

标签:C#,Lambda,表达式
0
投稿

猜你喜欢

  • SpringBoot配置Profile实现多环境支持

    2023-07-29 21:53:20
  • Android app应用多语言切换功能实现

    2023-12-27 22:06:27
  • hadoop是什么语言

    2021-06-18 07:02:38
  • Android 实现卡片堆叠钱包管理动画效果

    2021-12-12 11:15:02
  • C#实现一键换IP、重置DNS、网关及掩码的方法

    2021-10-03 00:32:33
  • Maven工程打包jar的多种方式

    2022-12-15 06:54:46
  • Java 高并发的三种实现案例详解

    2023-12-16 10:57:30
  • dotnet如何将文件删除到回收站

    2023-04-23 13:52:09
  • 配置tjxCold(idea效率插件)的模版教程详解

    2022-12-20 21:17:57
  • C#支付宝新版支付请求接口调用

    2023-02-23 15:50:45
  • Android中Toolbar随着ScrollView滑动透明度渐变效果实现

    2023-10-08 21:06:50
  • c#保存窗口位置大小操作类(序列化和文件读写功能)

    2023-07-15 18:51:06
  • Java多线程之彻底搞懂线程池

    2023-12-18 23:54:09
  • C#完成word文档打印的方法

    2023-05-29 23:55:36
  • Java中的StringBuilder性能测试

    2021-09-11 03:38:20
  • Android检测Activity或者Service是否运行的方法

    2021-09-03 00:52:00
  • c#模拟js escape方法的简单实例

    2023-01-26 07:29:24
  • 使用Enumeration和Iterator遍历集合类详解

    2023-01-05 11:57:51
  • java读写ini文件、FileOutputStream问题

    2023-11-29 08:50:13
  • 详解Java实践之建造者模式

    2023-01-14 23:03:13
  • asp之家 软件编程 m.aspxhome.com