C#中的闭包捕获问题

闭包捕获问题(Closure Capture Issue)是编程中一个常见的陷阱,尤其在循环内创建委托(如Lambda表达式)时容易遇到。在C#中,闭包(Closure)会捕获变量本身,而不是变量的值,这可能导致循环中的多个委托共享同一个变量,最终得到意外的结果。


例子

for (int i = 0; i < 10; i++)
{
    // 直接捕获循环变量i
    btn[i].onClick.AddListener(() => AddDigit(i.ToString()));
}

这段代码有个问题,无论点击哪个按钮,最终传入 AddDigit 的值都会是 10(循环结束时 i 的值),而不是按钮对应的 0-9

问题产生的原因

  1. 闭包捕获的是变量,不是值

    • Lambda表达式 () => AddDigit(i.ToString()) 中的 i 是循环变量,而不是循环迭代时的值。
    • 所有按钮的点击事件都会共享同一个变量 i
  2. 循环结束后变量 i 的值是 10

    • 当循环结束时,i 的值是 10(因为循环条件是 i < 10,最后一次循环后 i++ 使其变成 10)。
    • 用户点击按钮时,事件触发的是当前 i 的值,也就是 10

解决方法:

for (int i = 0; i < 10; i++)
{
    int num = i; // 每次循环都创建一个新的num
    btn[i].onClick.AddListener(() => AddDigit(num.ToString()));
}

其它闭包捕获问题的例子

for (int i = 0; i < 3; i++)
{
    // 直接捕获i
    Task.Run(() => Console.WriteLine(i));
}

输出结果可能是 3, 3, 3,而不是预期的 0, 1, 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值