3

Lambda 表达式在编译时进行评估,因此下面的代码不会生成 100 个不同的函数。是否有一种简单的机制来实现上述效果?我意识到这不是很有效的表现方式。

List<Action> actions = new List<Action>();
for (int i = 0; i < 100; ++i)
    actions.Add(() => Execute(100100100 + i));
4

2 回答 2

2

Lambda 表达式在编译时进行评估,因此下面的代码不会生成 100 个不同的函数。

我不确定你所说的这个声明是什么意思。如果您尝试创建 100 个委托,每个委托绑定到 的不同值i,那么您需要复制ifor循环内的临时变量中,以确保闭包不会都引用i. (有关详细信息,请参阅 dasblinkenlight 的答案。)

但在这种特殊情况下,您可以只使用 LINQ:

List<Action> actions = Enumerable.Range(0, 100)
    .Select(i => (Action)(() => Execute(100100100 + i)))
    .ToList();

或者,如果您更喜欢使用循环并且正在使用 .NET 4.5 或更高版本,则可以使用foreachwith Enumerable.Range

List<Action> actions = new List<Action>();
foreach (int i in Enumerable.Range(0, 100))
    actions.Add(() => Execute(100100100 + i));
于 2013-08-25T15:53:34.407 回答
2

这段代码关闭了一个修改过的变量,所以它不会做你想让它做的事情。您需要为 的值添加一个临时变量i,如下所示:

List<Action> actions = new List<Action>();
for (int i = 0; i < 100; ++i) {
    int temp = i;
    actions.Add(() => Execute(100100100 + temp));
}

要创建 100 个单独的 lambda,您可以创建 LINQ 表达式来调用Execute,一一构建常量,然后编译 lambda。但是,这不太可能给您带来很大的性能改进。这是您的操作方法:

var exec = typeof(Test).GetMethod("Execute"); // <<== Use your type here
var actions = new List<Action>();
for (int i = 0 ; i != 100 ; i++) {
    var val = Expression.Constant(i+100100100);
    // This assumes that Execute(int) is static.
    // For non-static calls use a different overload.
    var call = Expression.Call(exec, val);
    var lambda = Expression.Lambda(typeof(Action), call, new ParameterExpression[0]);
    actions.Add((Action)lambda.Compile());
}

这是关于 ideone 的演示

于 2013-08-25T15:56:18.547 回答