Loading

C#教程 - Lambda Expressions

更新记录
转载请注明出处:https://www.cnblogs.com/cqpanda/p/16690958.html
2022年9月17日 发布。
2022年9月10日 从笔记迁移到博客。

Lambda Expressions说明

在匿名函数的基础上删除delegate关键字

在参数列表和函数体之间添加=>符号

语法:

(parameters) => expression-or-statement-block

实例:

image

实例:

delegate int Transformer (int i);
Transformer sqr = x => x * x;

更简化的Lambda

image

Lambda本质

Lambda表达式最终会转为delegate instance或者expression tree

编译器转换实现

本质上编译器通过编写私有方法并将Lambda表达式的代码移到该方法中来解析

在编译器内部,lambda表达式会被转为类型的private方法

编译器会将Lambda表达式转为:

​ 一个委托的实例(A delegate instance)

​ 一个表达式树(expression tree, of type Expression, representing the code inside the lambda expression in a traversable object model. This allows the lambda expression to be interpreted later at runtime)

​ 如果有捕获的外部变量,则转为类的私有字段进行处理

捕获外部变量(Capturing Outer Variables)

说明

Variables can also be captured by anonymous methods and local methods

注意:变量的捕获发生在运行阶段

简单捕获变量

A lambda expression that captures variables is called a closure

实例:

static void Main()
{
  int factor = 2;
  Func<int, int> multiplier = n => n * factor;
  Console.WriteLine (multiplier (3));           // 6
}

被捕获变量调用时间

捕获变量会在lambda方法被调用的时候才会被引用,而不是在lambda表达式定义的时候

实例:

int factor = 2;
Func<int, int> multiplier = n => n * factor;
factor = 10;
Console.WriteLine (multiplier (3));           // 30

实例:最终输出333

Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
{
    actions [i] = () => Console.Write (i);
}
foreach (Action a in actions) a(); // 333

实例:最终输出012

Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
{
    int loopScopedi = i;
    actions [i] = () => Console.Write (loopScopedi);
}
foreach (Action a in actions) a(); // 012

捕捉for迭代变量(Capturing iteration variables)

When you capture an iteration variable in a for loop,

C# treats the iteration variable as though it were declared outside the loop

注意:foreach没有这个问题(C# 5.0+)

实例:

Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
  actions [i] = () => Console.Write (i);
foreach (Action a in actions) a();     // 333

如果非要捕获for循环中的当时的值,可以使用临时变量(temporary variable)

实例:

Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
{
  int loopScopedi = i;
  actions [i] = () => Console.Write (loopScopedi);
}
foreach (Action a in actions) a();     // 012

Lambda表达式与本地方法(Lambda Expressions Versus Local Methods)

比较

本地方法可以是递归的,自己调用自己

本地方法可以避免指定委托类型的混乱

本地方法的开销稍微少一点

匿名方法(Anonymous Methods)

Lambda表达式与匿名方法比较

Lambda表达式有隐式类型(参数Implicitly typed parameters)

Lambda表达式有表达式语法(Expression syntax)

匿名方法必须有语句块(statement block)

Lambda表达式可以编译为表达式树(expression tree, by assigning to Expression

匿名方法可以完全省略参数声明

实例

实例:

delegate int Transformer (int i);
Transformer sqr = delegate (int x) {return x * x;};
Console.WriteLine (sqr(3)); // 9

实例:省略参数声明

public event EventHandler Clicked = delegate { };

实例:事件监听函数使用匿名方法

// Notice that we omit the parameters:
Clicked += delegate { Console.WriteLine ("clicked"); };

实例:Using Lambda Expressions as Data

persons.Where(person => person.Name.ToUpper() == "INIGOMONTOYA");

Anonymous Function Terminology plication

image

Lambda表达式与编译器

Lambda expressions (and anonymous methods) are not intrinsically built in to the CLR

Rather, when the compiler encounters an anonymous function

it translates it into special hidden classes, fields, and methods that implement the desired semantics

The C# compiler generates the implementation code for this pattern so that developers do not have to code it themselves

The Lambda Expression Tree Type

image

分类

表达式式

​ 实现

​ x=>x

语句式

​ 实现

​ (int x) = > { return x;}

posted @ 2022-09-17 07:16  重庆熊猫  阅读(189)  评论(0编辑  收藏  举报