【C#补全计划】Lambda表达式
一、lambda表达式的概念
1. 可以将lambda表达式理解为匿名函数的简写
2. lambda表达式除了写法不同外,使用上和匿名函数一模一样,都是配合委托或事件使用的
二、lambda表达式的语法
1. 语法:
(1)匿名函数
delegate (参数列表) {
// 代码块
}
(2)lambda表达式
(参数列表) => {
// 代码块
}
三、lambda表达式的使用
1. 无参无返回值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();}}
}
2. 有参无返回值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);}}
}
3. 参数类型可以省略:与委托或事件容器一致
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");}}
}
4. 无参有返回值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);}}
}
5. 有参有返回值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);}}
}
6. 作为函数参数传递
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);Test test = new Test();// 作为函数参数传递test.toDo("使用其他参数", () =>{Console.WriteLine("作为参数传递的lambda表达式");});}}class Test{public Action action;// 作为参数传递时public void toDo(string s, Action a){Console.WriteLine(s);a.Invoke();}}
}
7. 作为函数返回值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);Test test = new Test();// 作为函数参数传递test.toDo("使用其他参数", () =>{Console.WriteLine("作为参数传递的lambda表达式");});// 作为函数返回值test.getFun()(); // 直接调用返回的委托函数}}class Test{public Action action;// 作为参数传递时public void toDo(string s, Action a){Console.WriteLine(s);a.Invoke();}// 作为返回值public Action getFun(){return () =>{Console.WriteLine("作为返回值返回的lambda表达式");};}}
}
运行结果如下:
四、闭包
1. 概念:内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止
2. 代码:
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);Test test = new Test();// 作为函数参数传递test.toDo("使用其他参数", () =>{Console.WriteLine("作为参数传递的lambda表达式");});// 作为函数返回值test.getFun()(); // 直接调用返回的委托函数}}class Test{public Action action;// 作为参数传递时public void toDo(string s, Action a){Console.WriteLine(s);a.Invoke();}// 作为返回值public Action getFun(){return () =>{Console.WriteLine("作为返回值返回的lambda表达式");};}}class Test2{public event Action action;public Test2(){int value = 10;// 闭包// 当构造函数执行完毕时,声明的临时变量value的生命周期被改变了action = () =>{Console.WriteLine(value); };}public void toDo(){action.Invoke();}}
}
运行结果如下:
3. 注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);Test test = new Test();// 作为函数参数传递test.toDo("使用其他参数", () =>{Console.WriteLine("作为参数传递的lambda表达式");});// 作为函数返回值test.getFun()(); // 直接调用返回的委托函数// 闭包Test2 test2 = new Test2();test2.toDo();}}class Test{public Action action;// 作为参数传递时public void toDo(string s, Action a){Console.WriteLine(s);a.Invoke();}// 作为返回值public Action getFun(){return () =>{Console.WriteLine("作为返回值返回的lambda表达式");};}}class Test2{public event Action action;public Test2(){int value = 100;// 闭包// 当构造函数执行完毕时,声明的临时变量value的生命周期被改变了action = () =>{Console.WriteLine(value); };// 注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值for (int i = 0; i < 10; i++) {action += () =>{Console.WriteLine(i);};}}public void toDo(){action.Invoke();}}
}
运行结果如下:(输出的不是0~9,而是i的最终值10)
4. 若想输出0~9,修改如下:
using System;namespace LambdaExpression
{class Program{static void Main(string[] args){// 无参无返回值Action action1 = () =>{Console.WriteLine("无参无返回值的lambda表达式");};action1.Invoke();// 有参无返回值Action<int> action2 = (int a) =>{Console.WriteLine("有参无返回值的lambda表达式");};action2.Invoke(10);// 参数类型可以省略:与委托或事件容器一致Action<int, string> action3 = (a, s) =>{Console.WriteLine("省略参数类型的lambda表达式");};action3.Invoke(10, "hello");// 无参有返回值Func<string> function1 = () =>{return "无参有返回值的lambda表达式";};string s1 = function1.Invoke();Console.WriteLine(s1);// 有参有返回值Func<int, string> function2 = (int a) =>{return "有参有返回值的lambda表达式";};string s2 = function2.Invoke(10);Console.WriteLine(s2);Test test = new Test();// 作为函数参数传递test.toDo("使用其他参数", () =>{Console.WriteLine("作为参数传递的lambda表达式");});// 作为函数返回值test.getFun()(); // 直接调用返回的委托函数// 闭包Test2 test2 = new Test2();test2.toDo();}}class Test{public Action action;// 作为参数传递时public void toDo(string s, Action a){Console.WriteLine(s);a.Invoke();}// 作为返回值public Action getFun(){return () =>{Console.WriteLine("作为返回值返回的lambda表达式");};}}class Test2{public event Action action;public Test2(){int value = 100;// 闭包// 当构造函数执行完毕时,声明的临时变量value的生命周期被改变了action = () =>{Console.WriteLine(value); };// 注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值for (int i = 0; i < 10; i++) {int index = i; // 每次循环都会创建一个新的index变量action += () =>{Console.WriteLine(index);};}}public void toDo(){action.Invoke();}}
}
运行结果如下:
今天的学习就到这里了。感谢阅读。
再见!