将委托转换为表达式树

时间:2010-01-22 11:05:41

标签: c# reverse-engineering expression-trees

我想知道您是否可以从现有委托创建和修改表达式树。

有点像

public void Foo() {
  Console.WriteLine(1000); 
}
....
Expression exp = Foo.GetExpression(); 
//Now do something what changes 1000 to 2000...

所以我想对已经完全排除的方法进行逆向工程。

我的问题是我有这样的结构:

var acts = new Action[20];

for (int i = 0; i != 20; i++)        
    acts[i] = () => { Console.WriteLine(i); };

并且通过C#的工作方式,所有行为都是相同的(打印20)。但我想要那个

acts[5]() 

打印5

acts[11]() 

打印11,依此类推。

所以我需要计算20个不同的代表,我想知道这是一个“好”的方法。我当然可以写:

acts[0] = () => Console.WriteLine(0); 
acts[1] = () => Console.WriteLine(1); 
acts[2] = () => Console.WriteLine(2); 
acts[3] = () => Console.WriteLine(3); 
.... 

但这不是我眼中的好方法......

2 个答案:

答案 0 :(得分:3)

Anton的解决方案几乎正确,但他正在错误的时间复制变量。你想要这个:

for (int i = 0; i != 20; i++)
{
    int tmp = i;
    acts[i] = () => Console.WriteLine(tmp);
}

这样捕获的变量tmp而不是i - 而且只有一个i变量,其值在每次迭代时都会发生变化,每次迭代都有一个“新的”tmp变量。

有关详情,请参阅Eric Lippert关于该主题的博文(part 1part 2)。

(要根据标题回答原始问题 - 您无法在此处以有用的方式从委托创建表达式树 - 您可以创建的唯一表达式树是仅调用原始委托的表达式树。)

答案 1 :(得分:2)

像这样改写:

for(int i = 0; i != 20; i++)        
{
    var x = i;
    acts[i] = () => { Console.WriteLine(x); };
}