谁能告诉我,这段代码怎么可能:
for (byte i = 0; i < someArray.Length; i++)
{
pool.QueueTask(() =>
{
if (i > 0 && i < someArray.Length)
{
myFunction(i, someArray[i], ID);
}
});
}
落在 myFunction
被 IndexOutOfRangeException
调用的那一行,因为 i
变量的值等于 someArray.Length
?我真的不明白...
注意:pool
是一个简单线程池的实例,有 2 个线程。
注意2:for循环中的类型byte
是有意放置的,因为数组长度不能超过字节最大值(根据前面创建数组的逻辑),我需要变量i
为 byte
类型。
最佳答案
您的代码在 i
上创建了一个闭包,每次执行时它都会变成 someArray.Length
。您最终传递给 QueueTask()
的 Action
保留 for 循环的状态,并在执行时使用 i
的值。这是表达同样问题的可编译代码示例,
static void Main(string[] args)
{
var someArray = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var fns = new List<Action>();
for (int i = 0; i < someArray.Length; i++)
{
fns.Add(() => myFunction(i, someArray[i]));
}
foreach (var fn in fns) fn();
}
private static void myFunction(int i, int v)
{
Console.WriteLine($"{v} at idx:{i}");
}
您可以通过在本地复制封闭的周围变量来打破这一点,它在 Action
创建时保留 i
的值。
static void Main(string[] args)
{
var someArray = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var fns = new List<Action>();
for (int i = 0; i < someArray.Length; i++)
{
var local = i;
fns.Add(() => myFunction(local, someArray[local]));
}
foreach (var fn in fns) fn();
}
private static void myFunction(int i, int v)
{
Console.WriteLine($"{v} at idx:{i}");
}
相关阅读:http://csharpindepth.com/Articles/Chapter5/Closures.aspx
关于c# - lambda 表达式中不可能的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33722405/