2009-08-21 16 views

Odpowiedz

50

Musisz przypisać lambda do innego typu:

// Gives you a delegate: 
Func<int, int> f = x => x * 2; 
// Gives you an expression tree: 
Expression<Func<int, int>> g = x => x * 2; 

To samo dotyczy argumentów metod. Jednak po przypisaniu takiego wyrażenia lambda do typu Func<>, nie można odzyskać drzewa wyrażeń.

+3

Delegat jest lepszym terminem niż lambda, w pierwszym przypadku. Oba wyrażenia lambda, jedno niejawnie konwertowane na anonimowego delegata, inne drzewo wyrażeń. – nawfal

+0

@nawfal * 'f' * jest delegatem. Ale 'x => x * 2' jest wyrażeniem lambda (jak sam zauważyłeś). Twój komentarz sugeruje, że powiedziałem coś innego, ale tak naprawdę nie. –

+1

Powiedziałeś, że drugie wyrażenie daje ci drzewo wyrażenia. Analogicznie do tego, pierwsze wyrażenie lambda powinno * dać delegatowi *, a nie * lambda * - który jest twoim pierwszym komentarzem. Nie nitpicking, tylko wspominając, aby pomóc komuś w przyszłości. – nawfal

10

Odpowiedź Konrada jest dokładna. Aby kompilator wygenerował drzewo wyrażeń, należy przypisać wyrażenie lambda do Expression<Func<...>>. Jeśli uzyskasz lambdę jako Func<...>, Action<...> lub inny typ delegata, wszystko, co masz, to garść instrukcji IL.

Jeśli naprawdę potrzebujesz, aby móc skonwertować skompilowaną z IL lambdę z powrotem do drzewa ekspresji, musisz ją zdekompilować (np. Zrobić to, co robi narzędzie Reflector Lutza Roedera). Sugeruję przejrzenie biblioteki Cecil, która zapewnia zaawansowaną obsługę manipulacji IL i może zaoszczędzić sporo czasu.

6

Po to, by rozwinąć odpowiedź Konrada i poprawić Pierre'a, wciąż można wygenerować wyrażenie z lambdy skompilowanej z IL, choć nie jest to zbyt eleganckie. Rozszerzanie przykładu Konrada:

// Gives you a lambda: 
Func<int, int> f = x => x * 2; 

// Gives you an expression tree: 
Expression<Func<int, int>> g = x => f(x); 
+11

To ** nie ** daje ci drzewa wyrażeń oryginalnego lamda, daje ** nowe ** drzewo wyrażeń, które wywołuje delegata. Nic więcej. – Aidiakapi

+0

Pytanie nie dotyczy uzyskania * równoważnego * wyrażenia. Dla LINQ in-memory zapewnia to identyczną funkcjonalność. Oczywiście nie można go poprawnie przeanalizować przez żadnego dostawcę LINQ. – joniba