C#通过Lambda表达式实现闭包

发布时间 2023-03-25 17:21:13作者: 笠侹凯树

背景

c#是一门面向对象的编程语言,所以C#中以对象作为最小粒度,如果要存储状态信息,当然是存储在对象(或类)中。方法(函数)本身是没有状态的,每一次执行都是完全一致的。

我们先看这样一个例子,让方法记住上一个状态。

从控制台的输出可以看出,"Hello"之后传null,打印的仍为"Hello"。当由null改为"你好",控制台更改为"你好",并记住“你好”的这个状态,传null也打印你好。

 1 namespace deom01_state_func
 2 {
 3     class Test
 4     {
 5         string msg = "";
 6 
 7         public void WriteLine(string info = null)
 8         {
 9             if (!string.IsNullOrEmpty(info))
10             {
11                 msg = info;
12             }
13             Console.WriteLine(msg);
14         }
15     }
16 }
Test代码

 

某些时候我们希望函数能存储状态,C语言中可以使用静态局部变量,但C#不支持静态局部变量。

为了解决C#的函数能够存储状态的问题,使用内部类虽然可以达到效果,但是代码量在无形中增加了。所以,引入闭包解决函数存储状态的问题,又减少了一定的代码量。

闭包

闭包是一种语言特性,它允许在函数内部定义的函数访问外部函数的局部变量。即使外层函数执行已终止。在C#中我们可以使用Lambda来实现闭包。闭包返回的其实是一个对象。

看一下通过闭包实现背景的例子

 

 1 namespace deom01_state_func
 2 {
 3     class Test2
 4     {
 5         public Action<string> CreateWrite()
 6         {
 7             string msg = "";
 8 
 9             return (string info) =>
10             {
11                 if (!string.IsNullOrEmpty(info))
12                 {
13                     msg = info;
14                 }
15                 Console.WriteLine(msg);
16             };
17         }
18     }
19 }
闭包

 

应用

我们在winform应用程序中,应用闭包记住输入的值,从而达到求和、累加输入次数、取平均值

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 
11 namespace demo01_state_func_winform
12 {
13     public partial class Form1 : Form
14     {
15         public Form1()
16         {
17             InitializeComponent();
18             this.button1.Click += btnAvgClick();
19         }
20 
21         public EventHandler btnAvgClick()
22         {
23             double sum = 0;
24             int count = 0;
25 
26             return (sender, e) =>
27             {
28                 sum += double.Parse(textBox1.Text);
29                 count++;
30                 label1.Text = string.Format("sum={0},\t count={1}, \t avg={2}", sum, count, (sum / count));
31             };
32         }
33 
34         private void Form1_Load(object sender, EventArgs e)
35         {
36 
37         }
38     }
39 }
应用闭包