Преобразование делегата в дерево выражений - PullRequest
1 голос
/ 22 января 2010

Интересно, можете ли вы создать и изменить дерево выражений из существующего делегата.

Вроде как

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 ]

3 голосов
/ 22 января 2010

Правильное решение Антона почти , но он копирует переменную не в то время.Вы хотите это:

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

Таким образом, захваченная переменная имеет значение tmp, а не i - и хотя существует только одна переменная i, значение которой изменяется на каждой итерациивы получаете «новую» переменную tmp для каждой итерации.

См. сообщения Эрика Липперта в блоге на эту тему ( часть 1 , часть 2 ) для получения дополнительной информации.детали.

(Чтобы ответить на исходный вопрос согласно заголовку - вы не можете создать дерево выражений из делегата полезным способом - единственное дерево выражений, которое вы можете создать, это то, которое просто вызывает оригиналделегировать.)

2 голосов
/ 22 января 2010

Перепишите это так:

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