You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#循环初始化带固定索引的Func数组不生效问题求助

问题根因

这是C#闭包的经典问题:for循环里的lambda捕获的是循环变量i本身,不是创建lambda那一刻i的拷贝值。等整个循环执行完成后,i的值固定为10,这时候无论调用数组中哪个委托,读取的都是这同一个i变量,因此所有调用都会等价于执行Convert(10, myVal)。

正确实现方式

写法1:兼容所有C#版本的循环写法

只需要在循环内部声明一个独立的局部变量,将当前轮次的i值拷贝给它即可——每轮循环的局部变量是完全独立的,lambda捕获这个局部变量就不会出现值被覆盖的问题:

var myfunctions= new Func<ushort, double>[10];
for (int i=0; i<10; i++)
{
   int currentIdx = i; // 每轮循环单独存储当前索引
   // 注意:原代码lambda内写的`in`是笔误,替换为传入参数x_in
   myfunctions[i] = x_in => Convert(currentIdx, x_in);
}

这个写法的运行效果和你逐行硬编码完全一致,没有冗余代码。

写法2:LINQ简洁写法(C# 3.0及以上可用)

如果项目允许使用LINQ,可以直接一行生成整个函数数组,天然规避闭包捕获问题:

using System.Linq;

var myfunctions = Enumerable.Range(0, 10)
    .Select<int, Func<ushort, double>>(idx => x_in => Convert(idx, x_in))
    .ToArray();

这里的idx是Select迭代时传入的形参,每一轮迭代的idx都是独立的值,不存在多个lambda共享同一个变量的问题,代码更简洁也不容易写错。

补充说明:C# 5.0仅调整了foreach循环的闭包捕获逻辑,for循环的变量捕获逻辑从未变更,即便是最新版本的.NET,直接在for循环的lambda中捕获循环变量i依然会触发这个问题。

内容的提问来源于stack exchange,提问作者Yannick Favre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:25:03