在C#中的运行时构造一个函数
本文关键字:一个 函数 运行时 | 更新日期: 2023-09-27 18:28:53
Lambda表达式在编译时求值,因此下面的代码不会生成100个不同的函数。有没有一个简单的机制可以达到上述效果?我意识到这在性能方面不是很有效。
List<Action> actions = new List<Action>();
for (int i = 0; i < 100; ++i)
actions.Add(() => Execute(100100100 + i));
这段代码关闭了一个修改过的变量,所以它不会做你想做的事情。你需要为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上的演示。
Lambda表达式是在编译时计算的,因此下面的代码不会生成100个不同的函数。
我不知道你说的这句话是什么意思。如果您试图创建100个委托,每个委托都绑定到不同的i
值,那么您需要将i
复制到for
循环内的一个临时变量中,以确保闭包不会全部引用相同的i
实例。(请参见dasblinkenlight对细节的回答。)
但在这种特殊情况下,您可以使用LINQ:
List<Action> actions = Enumerable.Range(0, 100)
.Select(i => (Action)(() => Execute(100100100 + i)))
.ToList();
或者,如果您喜欢使用循环并且使用.NET 4.5或更高版本,则可以将foreach
与Enumerable.Range
:一起使用
List<Action> actions = new List<Action>();
foreach (int i in Enumerable.Range(0, 100))
actions.Add(() => Execute(100100100 + i));