闭包(Closure)是一种强大的编程概念,它允许函数捕获并记住其定义时的环境上下文。在C#中,闭包使得函数可以访问并操作其词法作用域之外的变量。这个东西在JS中用的太多了。
闭包本质上是一个函数,它能够"记住"并访问其创建时的环境变量,即使这些变量已经超出了原始作用域。
C#public class ClosureDemo
{
public static Func<int> CreateCounter()
{
// count 是被捕获的局部变量
int count = 0;
// 返回一个匿名函数(闭包)
return () =>
{
count++; // 闭包可以修改外部变量
return count;
};
}
public static void Main()
{
// 创建两个独立的计数器
var counter1 = CreateCounter();
var counter2 = CreateCounter();
Console.WriteLine(counter1()); // 输出: 1
Console.WriteLine(counter1()); // 输出: 2
Console.WriteLine(counter2()); // 输出: 1 (独立的计数器)
}
}
C#namespace AppClosure
{
internal class Program
{
public static void LoopClosure()
{
// 常见的闭包陷阱
var actions = new List<Action>();
for (int i = 0; i < 5; i++)
{
// 这里会捕获循环变量i的引用,而非值
actions.Add(() => Console.WriteLine(i));
}
// 实际输出会是 5 5 5 5 5
foreach (var action in actions)
{
action();
}
// 解决方案:使用局部变量捕获当前值
var correctActions = new List<Action>();
for (int i = 0; i < 5; i++)
{
int localI = i; // 创建局部副本
correctActions.Add(() => Console.WriteLine(localI));
}
// 现在会正确输出 0 1 2 3 4
foreach (var action in correctActions)
{
action();
}
}
static void Main(string[] args)
{
LoopClosure();
}
}
}
C#namespace AppClosure
{
internal class Program
{
// 创建一个带有预设参数的函数
public static Func<int, int> Multiplier(int factor)
{
// 闭包捕获factor
return x => x * factor;
}
public static void Demonstrate()
{
var doubler = Multiplier(2);
var tripler = Multiplier(3);
Console.WriteLine(doubler(5)); // 输出: 10
Console.WriteLine(tripler(5)); // 输出: 15
}
static void Main(string[] args)
{
Demonstrate();
}
}
}
闭包是C#中一个强大且灵活的特性,它允许函数携带其创建时的上下文。正确理解和使用闭包,可以编写更加简洁和表达性强的代码。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!