调用Func 时为什么会出错?
我在C#中有以下代码片段:
var actions = new List<Func>(); IEnumerable values = new List { 1, 2, 3 }; foreach (int value in values) { actions.Add(() => value * value); } foreach (var action in actions) { Console.WriteLine(action()); ; } Console.ReadLine();
它运行正常,但我没有得到我期望的结果。
实际结果
9,9,9
预期结果
1,4,9
为什么我没有得到我期望的结果?
您正在捕获lambda表达式中的循环变量,这意味着当最终调用委托时,它会看到循环变量的最终值。
简单修复:
foreach (int value in values) { int copy = value; actions.Add(() => copy * copy); }
这样,您就可以在循环的每次迭代中获得一个新的copy
变量,因此每个委托表达式将捕获一个不同的变量,并且它们不会受到随时间变化的循环变量( value
)的影响。
Eric Lippert在“关闭循环变量被认为有害” (以及第二部分 )中对此做了很好的解释。
基本上这是C#中的“陷阱”,几乎每个人都迟早会失败。
您需要捕获循环内的变量。 现在,您的延迟执行操作正在使用第一个foreach
循环中的最后一个值。
var actions = new List>(); IEnumerable values = new List { 1, 2, 3 }; foreach (int value in values) { var v = value; actions.Add(() => v * v); } foreach (var action in actions) { Console.WriteLine(action()); ; } Console.ReadLine();
注意var v = value;
线。
- YouTube API – 从用户限制中获取所有video?
- System.Threading.Timer vs System.Threading.Thread.Sleep resolution – .NET Timer不使用系统时钟分辨率
- 将ICC颜色配置文件应用于C#(Dotnet)中的图像
- 拆除逗号分隔的字符串,同时删除空格和空条目
- TcpListener排队连接的速度比我清除它们的速度快
- 动态忽略控制器上的WebAPI方法以获取api资源管理器文档
- entity framework4.1代码第一外键ID
- 如果方法的最后一个参数用’params’标记,reflection是否会暴露?
- 为什么C#处理命令行参数不一致?