闭包意义与使用

news/2025/1/15 13:58:25/

闭包是一个编程概念,指的是一个函数可以访问其定义时所在的词法作用域中的变量,即使该函数在其定义时已经离开了该作用域。这意味着,如果一个函数引用了一个外部变量,那么该变量会被自动捕获到闭包中,并在函数执行时可以访问到。

具体来说,闭包由两部分组成:一个是函数对象,另一个是该函数所引用的所有变量的值的集合。这些变量的值被捕获到闭包中,并在函数执行时可以访问到。在 JavaScript 中,这个过程被称为“变量捕获”或“闭包捕获”。

闭包可以方便地实现许多功能,例如实现事件监听器、延迟执行等。但是,滥用闭包也可能会导致内存泄漏等问题,因此在编写代码时,需要注意避免出现不必要的闭包对象。

闭包可以通过 lambda 表达式来实现。以下是一个使用闭包实现延迟执行的示例代码:

using System;
using System.Threading;class Program
{static void Main(string[] args){Func<int, Action> delayedPrint = (delay) => () =>{Thread.Sleep(delay);Console.WriteLine("Delayed print after {0}ms", delay);};Console.WriteLine("Start...");var action1 = delayedPrint(1000);var action2 = delayedPrint(2000);var action3 = delayedPrint(3000);Console.WriteLine("Waiting...");action1();action2();action3();Console.WriteLine("Done.");}
}

定义了一个函数 delayedPrint,它接受一个延迟时间作为参数,返回一个函数对象,该函数对象会在指定的延迟时间后输出一条消息到控制台上。这个函数对象使用了闭包,捕获了延迟时间的值,并在函数执行时访问该值。

在 Main 函数中,我们使用 delayedPrint 函数创建了三个延迟执行的函数对象,并依次执行它们。由于这些函数对象使用了闭包,因此它们在执行时可以访问到延迟时间的值,实现了延迟执行的功能。

此外,闭包还可以用于实现事件监听器。例如,以下是一个使用闭包实现简单事件系统的示例代码:

using System;class Program
{static void Main(string[] args){var eventSystem = new EventSystem();var listener1 = new EventListener("Listener1");var listener2 = new EventListener("Listener2");eventSystem.AddListener("Event1", listener1.OnEvent);eventSystem.AddListener("Event1", listener2.OnEvent);eventSystem.TriggerEvent("Event1", "Hello world!");}
}class EventSystem
{private Dictionary<string, List<Action<string>>> _listeners = new Dictionary<string, List<Action<string>>>();public void AddListener(string eventName, Action<string> listener){if (!_listeners.ContainsKey(eventName)){_listeners[eventName] = new List<Action<string>>();}_listeners[eventName].Add(listener);}public void TriggerEvent(string eventName, string eventData){if (_listeners.ContainsKey(eventName)){foreach (var listener in _listeners[eventName]){listener(eventData);}}}
}class EventListener
{private string _name;public EventListener(string name){_name = name;}public void OnEvent(string eventData){Console.WriteLine("{0} received event: {1}", _name, eventData);}
}

首先定义了一个事件系统 EventSystem,它包含一个字典 _listeners,用于存储事件名和对应的监听器列表。EventSystem 类提供了 AddListener 和 TriggerEvent 方法,用于添加监听器和触发事件。

我们还定义了一个事件监听器 EventListener,它包含一个名称 _name,和一个 OnEvent 方法,用于接收事件并输出一条消息到控制台上。

在 Main 函数中,我们创建了两个事件监听器,并将它们添加到事件

系统中。我们使用 AddListener 方法向事件系统注册了两个监听器,它们都监听了名为 Event1 的事件。接着,我们调用了 TriggerEvent 方法,触发了 Event1 事件,并传递了一个字符串数据。由于 Event1 事件有两个监听器,因此每个监听器都会收到一条消息,输出到控制台上。

在这个例子中,监听器的 OnEvent 方法使用了闭包,捕获了监听器的名称 _name,并在函数执行时访问该值。这样,每个监听器都可以输出自己的名称,并显示收到的事件数据。

总之,闭包是一个非常有用的编程概念,可以方便地实现许多功能,包括延迟执行、事件监听器等。无论是 JavaScript 还是 C#,都可以使用闭包来简化代码,并提高程序的可读性和可维护性。


http://www.ppmy.cn/news/841210.html

相关文章

256GB+65W+90Hz,从4599元跌至3699元,12GB运存顶尖旗舰加速退场

手机8GB运行内存已经够用的情况下&#xff0c;你们会选择入手12GB运行内存的高配版吗&#xff1f;尽管12GB运行内存已经出来了接近两年&#xff0c;但是真正使用上12GB运行内存手机的人却并不多&#xff0c;因为8GB足以应付日常使用&#xff0c;追求12GB运行内存的高配版所带来…

hdu 4599 Dice

题目&#xff1a;hdu 4599 Dice tag &#xff1a;概率dp 思路&#xff1a;跟上次多校一样的思路&#xff1a;click here 所以知道&#xff1a;F(n)(6^n-1)/5 H(n)6*F(n) G(n)6*n 所以要求的是&#xff1a;m>(6^n-1)/30 所以最小的m是 &#xff08;6^n24&#xff09;/3…

Spring Boot---(7)SpringBoot多线程

前提&#xff1a; 日常开发&#xff0c;有很多场景会使用到多线程&#xff0c;比如&#xff0c;我们解析Excel&#xff0c;如果解析出一个3万条数据的Excel表格&#xff0c;需要两部&#xff1a; 1.我们需要先异步解析出所有的数据&#xff0c;前面写过了如何异步处理任务&…

Docker Quickstart Terminal启动报错“Unable to verify the Docker daemon”和步骤“Finalize”出错

Docker Quickstart Terminal启动报错“Unable to verify the Docker daemon”和步骤“Finalize”出错 1、Unable to verify the Docker daemon is listening: Maximum number of retries (10) exceeded2、Looks like something went wrong in step Finalize... Press any key t…

linux 挂载大容量硬盘

在linux中对于大于2T的硬盘&#xff0c;需要使用parted进行分区。 #1.确认要挂载的硬盘 fdisk -l Disk /dev/sdb: 10.9 TiB, 11999064883200 bytes, 23435673600 sectors Units: sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 4096 byt…

2049:【例5.19】字符串判等

2049&#xff1a;【例5.19】字符串判等 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 13135 通过数: 4599 【题目描述】 判断两个由大小写字母和空格组成的字符串在忽略大小写&#xff0c;且忽略空格后是否相等。 【输入】 两行&#xff0c;每行包含一个字符串。…

4599 的 iPhone 11,拼多多如何从「真香」到「更香」

每个工作日的早高峰&#xff0c;北京五环外的西二旗&#xff0c;每小时都有 2.5 万人涌出地铁站&#xff0c;这让西二旗成为这座城市最忙碌的地铁站。 交通部门的数据显示&#xff0c;根据 2017 年典型工作日&#xff0c;IC 卡乘客早高峰前 20 位站间 OD&#xff08;起终点间的…

DataX-Mysql主键UUID类型切分主键

一、问题背景 之前公司在使用datax时&#xff0c;需要从rds同步数据到hive&#xff0c;但是数据库中的主键id是uuid类型的字符串&#xff0c;使用datax默认的字符串分隔方式&#xff0c;其实会有很大的问题&#xff0c;所以官方也不推荐使用。 二. 分析源码 跟踪底层源码最终…