zoukankan      html  css  js  c++  java
  • Lambda表达式

    • Lambda表达式是写在委托实力上懂得匿名方法.编译器立即将lambda表达式转换成下面这两种形式
    1. 委托实例
    2. Expression<Tdelegate>类型的表达式树,该表达式树将lambda表达式内的代码显示为可遍历的对象模型,是表达式的解释可以延迟到运行时.
    • 下面的委托类型:

      delegate int Transformer(int i);

      可以指定和调用下面的x=>x*x lambda表达式:

      编译器内部将这种lambda表达式编译成一个私有方法,并把表达式代码移到该方法中.

    Transformer sqr=x=>x*x;
    Console,WriteLine(sqr(3)); //9
    View Code
    • Lambda表达式有一下形式:

      (参数)=>表达式或语句块

      在只有一个可推测类型的参数的时候,可以省略小括号.

      上面例子中,只有一个参数x,表达式为x*x:

      x=>x*x;

    • Lambda表达式使每个参数和委托的参数一致,表达式的类型(可以为void)和委托的返回值类型一致

      上面例子中,x和参数i一致,表达式x*x和返回值类型int一致,因此与Transformer委托相兼容

    • Lambda表达式代码可以是表达式,还可以是语句块,可以把以上的改成
      x=>{return x*x;};
      View Code
    • Lambda表达式通常和Func或Action委托一起使用,因此,修改以前的代码为
      Func<int,int>sqr=x=>x*x;
      View Code

      带两个参数的表达式

      Func<string,string,int>totalLength=(s1,s2)=>s1.Length+s2.Length;
      int total=totalLength("Hello","world");//total=10;
      View Code
    • 明确指定Lambda表达式参数类型.
      编译器通常可以根据上下文推断出lambda参数的类型,但是,当不能推断时,必须明确指定每个参数的类型
      Func<int,int>sqr=x=>x*x;
      View Code

      编译器可以推断出x是int类型,也可以显示的指定x的类型:

      Func<int,int>=(int x)=>x*x;
      View Code
    • Lambda表达式可以引用方法内的内部变量和参数(外部变量).
      static void Main(string[] args)
      {
            int factor = 2;
            Func<int, int> multiplier = n => n * factor;
            Console.WriteLine(multiplier(3));
            Console.ReadKey();
      }
      View Code

      结果为6.

    • Lambda表达式引用的外部变量称为捕获变量,捕获变量的表达式称为一个闭包.(捕获变量在真正调用委托时被赋值,而不是在捕获时赋值).
      static void Main(string[] args)
      {
             int factor = 2;
             Func<int, int> multiplier = n => n * factor;
             Console.WriteLine(multiplier(3));//6
             factor = 10;
             Console.WriteLine(multiplier(3));//30
             Console.ReadKey();
      }
      View Code

       Lambda表达式可以自动更新捕获变量;

      int seed = 2;
      Func<int> natural = () => seed++;
      Console.WriteLine(natural());//0
      Console.WriteLine(natural());//1
      Console.WriteLine(natural());//2
      View Code

      捕获变量的生命周期可以和委托的生命周期相同.以下例子中,局部变量seed本应在Natural执行完后消失,但是因为被捕获了,则,它的生命周期延长到和捕获它的委托natural的生命周期相同:

      static void Main(string[] args)
      {
           Func<int> natural = Natural();
           Console.WriteLine(natural());//0
           Console.WriteLine(natural());//1
      }
      static Func<int>Natural()
      {
            int seed = 0;
            return () => seed++;//返回一个闭包
      }
      View Code
    • 在Lambda表达式内实例化的局部变量,在每次调用委托实例期间是唯一的,如果我们把上例改成在lambda表达式内部实例化seed,程序结果会与之前不同:
      static void Main(string[] args)
      {
          Func<int> natural = Natural();
          Console.WriteLine(natural());//0
          Console.WriteLine(natural());//0
      }
      static Func<int>Natural()
      {
           return () => { int seed = 0; return seed++; };//返回一个闭包
      }
      View Code
    • 捕获循环变量
      当捕获for或foreach语句中的循环变量时,c#把这些循环变量看作是声明在循环外部的,这表名每个循环捕获的是相同的变量,
      Action[] actions = new Action[3];
      for (int i = 0; i < 3; i++)
      {
          actions[i] = () => Console.Write(i);
      }
      foreach (var item in actions)
      {
           item();//结果输出333,而不是012
      }
      Console.ReadKey();
      View Code

      每个闭包(Console.Write(i))捕获相同的变量,(如果变量i在循环中保持不变,则非常有用;甚至可以根据需要在循环体中显示修改i的值.),每个委托在调用的时候才看到i值,此时,i值为3(循环完成的最后值)

      Action[] actions = new Action[3];
      int i = 0;
      actions[0] = () => Console.Write(i);
      i = 1;
      actions[1] = () => Console.Write(i);
      i = 2;
      actions[2] = () => Console.Write(i);
      i = 3;
      //item调用的时候捕获最后一次i的值
      foreach (var item in actions) item();//333
      View Code

      想要输出012,

      Action[] actions = new Action[3];
      for (int i = 0; i < 3; i++)
      {
          int lo = i;
         actions[i] = () => Console.Write(lo);
      }
      foreach (var item in actions)item();//012
      View Code

      这样导致闭包每次循环中捕获不同的变量

  • 相关阅读:
    轮播图
    原生js实现分页效果(带实例)
    mint-ui Toast icon 图标
    阮小二买彩票
    js事件冒泡和事件捕捉
    html,css,js加载顺序
    单调栈-哈希表-768. 最多能完成排序的块 II
    同余问题-三整除系列
    动态规划-区间dp-单调栈-1130. 叶值的最小代价生成树
    动态规划-1Ddp-983. 最低票价
  • 原文地址:https://www.cnblogs.com/valiant1882331/p/4059489.html
Copyright © 2011-2022 走看看