在 C# 中,闭包是一个强大且常用的特性,它让你能够在一个函数内部访问其外部函数的变量,即使外部函数已经执行完毕。
定义和原理
闭包是指一个函数捕获并持有其外部作用域中变量的引用,即使该外部作用域已经结束。在 C# 里,当你在一个方法内部定义一个匿名方法、Lambda 表达式或者局部函数时,如果这些内部函数引用了外部方法的变量,就形成了闭包。这些被引用的外部变量的生命周期会被延长,直到闭包对象不再被引用。
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace _3.闭包讲解
{
class Program
{
static void Main(string[] args)
{
int value = 10;
//这个过程就是闭包:原理是把值存储在堆中,而不是栈中
Action action = () =>
{
Console.WriteLine($"捕获到的值:{value}");
};
value = 20;
action();
//for (int i = 0; i < 3; i++)
//{
// ThreadPool.QueueUserWorkItem(Work, i);
//}
//Thread.Sleep(1000);
//闭包:匿名函数捕获循环变量i
for (int i = 0; i < 3; i++)
{
//当前变量本来是个值,但由于写法闭包了,所以导致现在i变成了引用类型,所以导致循环的最终值是3,而不是预期的0,1,2
//创建一个新的局部变量,告诉循环,当匿名循环使用的时候使用的是一个新的值,而不是上一个引用
int index = i;
ThreadPool.QueueUserWorkItem(state =>
{
Console.WriteLine($"闭包线程:{Thread.CurrentThread.ManagedThreadId}:i = {index}");
});
}
}
static void Work(object state)
{
//变量是通过传参的形式进来的,并没有捕获外部的变量
int value = (int)state;
Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId}:value = {value}");
}
}
}