C#中Lambda表达式的用法

目录
  • 1.参数
  • 2.多行代码
  • 3.闭包
  • 4.使用foreach语句的闭包

从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运算符“=>” 的左边是参数列表,右边是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循环的代码中创建一个不同的局部循环变量。

到此这篇关于C#中Lambda表达式的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#中使用Lambda表达式自定义比较器实现两个列表合并实例

    一次项目有这样的需求,本地存储了json数据,可以转化为对应的List列表,现在需要更新,从服务器那里获取最新的数据更改.总的来说就是本地有个List表,如果数据需要更新,则会向服务器发送请求来获取需要更改的部分List表格,然后客户端这边就要去处理合并完整这次的更新,弄了一个下午,终于搞定,这次来mark一下. 主要推送的数据的两个特性: 1.如果之前的列表需要增加,则出现在最新的数据推送List中 2.如果数据需要修改的话,则一样推送更新,保持id不变,内容有所改变 示例代码如下图: 复制代

  • C#基础之Lambda表达式用法实例教程

    本文以实例形式介绍了C#中Lambda表达式的用法,分享给大家供大家参考之用.具体如下: 从委托的角度来看,Lambda表达式与匿名方法没有区别.在前面C#基础之匿名方法一文中,我们使用了匿名方法来调用List<T>的FindAll方法.从C# 3.0开始,在使用匿名方法的地方,完全可以用Lambda表达式来代替.Lambda表达式的定义方式为:"([参数列表]) => 表达式".运算符"=>"是一种与赋值运算"="具有相

  • C# lambda表达式应用如何找出元素在list中的索引

    1.先写个规则方法 private bool check(string str){ return str.EndsWith("xxx"); } 2.再写个Predicate Predicate<string> predicate=new Predicate<string>(check)); 如果逻辑不复杂,可以这样写 private void OpenMenu(GameObject gob){ Predicate<string> predicate=

  • C#匿名委托与Lambda表达式详解

    通过使用匿名委托(匿名方法),使编程变得更加灵活,有关委托与匿名委托请参考我的前一篇Blog<委托与匿名委托>. 继续之前示例,代码如下: static void Main(string[] args) { Worker.TwoNumberHandleMethodDelegate method = delegate(int a, int b) { return a + b; }; Worker worker = new Worker(); int result = worker.HandleT

  • 理解C#中的Lambda表达式

    先来看两段代码: 复制代码 代码如下: Thread t = new Thread(() => { AddIt AddDelegate = new AddIt(AddItem); this.Invoke(AddDelegate); }); Thread t3 = new Thread(new ThreadStart(() => { AddIt AddDelegate = new AddIt(AddItem); this.Invoke(AddDelegate); })); 这两种写法都是可以的,

  • C# 内部类与Lambda表达式用法详解

    目录 一.内部类 1.什么是内部类? 1.类作为形参和返回值: 2.内部类的几种形式 二.Lambda表达式(强调做什么,而不是以什么形式去做) 1.Lambda表达式的格式要求: 2.Lambda与匿名内部类的区别 1.省略模式 2.Lambda与匿名内部类的区别: 三.方法引用 1.方法的概述: 2.常见的方法引用方式: 3.方法引用的具体方式: 一.内部类 1.什么是内部类? 1.类作为形参和返回值: 抽象类作为形参和返回值: 通过多态的形式去传递抽象类作为形参的方法,方法的形参与返回值为

  • C# lambda表达式原理定义及实例详解

    定义:"Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式. 好处:Lambda简化了匿名委托的使用,减少开发中需要编写的代码量. 写法:所有Lambda表达式都使用Lambda运算符=>,该运算符读作"goes to".Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块.Lambda表达式x => x * x读作"x goes to x times x". 注:(左边)输入参数为1个时可以省略小

  • C#中方法的直接调用、反射调用与Lambda表达式调用对比

    想调用一个方法很容易,直接代码调用就行,这人人都会.其次呢,还可以使用反射.不过通过反射调用的性能会远远低于直接调用--至少从绝对时间上来看的确是这样.虽然这是个众所周知的现象,我们还是来写个程序来验证一下.比如我们现在新建一个Console应用程序,编写一个最简单的Call方法. 复制代码 代码如下: class Program {     static void Main(string[] args)     {             } public void Call(object o

  • C# 本地函数与 Lambda 表达式详细介绍

    目录 1.C# 本地函数与 Lambda 表达式 2.Lambda 表达式 3.本地函数 4.那么,局部函数的目的是什么? 1.C# 本地函数与 Lambda 表达式 C# 局部函数通常被视为 lambda 表达式的进一步增强.虽然功能是相关的,但也存在重大差异. Local Functions 是嵌套函数]功能的 C# 实现.一种语言在支持 lambdas 之后获得对嵌套函数的支持几个版本是有点不寻常的.通常情况相反. Lambda 或一般的一流函数需要实现未在堆栈上分配且生命周期与需要它们的

  • C# Lambda表达式用途深入理解

    假如我们想要从一个整型数组中取出其中是奇数的选项,其实现方式有很多,我们通过下面三种实现方式来对对比理解Lambda表达式的用途 方法一:命名方法 复制代码 代码如下: public class Common { public delegate bool IntFilter(int i); public static List<int> FilterArrayOfInt(int[] ints, IntFilter filter) { var lstOddInt = new List<in

  • C# Lambda表达式及Lambda表达式树的创建过程

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不爱说话,默默承受着编程的巨大压力,除了技术上的交流外,他们不愿意也不擅长和别人交流,更不乐意任何人走进他们的内心! 题外话说多了,咱进入正题: 上一节中,我们讲到:在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,La

随机推荐