2009-08-21 14 views

Respuesta

50

debe asignar el lambda a un tipo diferente:

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

Lo mismo ocurre con los argumentos del método. Sin embargo, una vez que haya asignado una expresión lambda de este tipo a un tipo Func<>, no podrá recuperar el árbol de expresiones.

+3

Delegado es un término mejor que lambda, en el primer caso. Ambas son expresiones lambda, una implícitamente convertida en un delegado anónimo, y otro un árbol de expresiones. – nawfal

+0

@nawfal * 'f' * es un delegado. Pero 'x => x * 2' es una expresión lambda (como usted mismo notó). Tu comentario implica que dije algo diferente pero realmente no lo hice. –

+1

Dijiste que la segunda expresión te da un árbol de expresiones. De forma análoga, la primera expresión lambda debería * darle un delegado *, no un * lambda * - que es lo que su primer comentario es. No es quisquilloso, solo lo menciono para que ayude a alguien en el futuro. – nawfal

10

La respuesta de Konrad es exacta. Debe asignar la expresión lambda a Expression<Func<...>> para que el compilador genere el árbol de expresiones. Si obtiene un lambda como Func<...>, Action<...> u otro tipo de delegado, todo lo que tiene es un montón de instrucciones IL.

Si realmente necesita poder convertir una lambda compilada IL en un árbol de expresiones, tendría que descompilarla (por ejemplo, hacer lo que hace la herramienta Reflector de Lutz Roeder). Sugeriría echarle un vistazo a la biblioteca Cecil, que proporciona soporte avanzado de manipulación de IL y podría ahorrarle bastante tiempo.

6

Solo para expandir la respuesta de Konrad y corregir a Pierre, aún puede generar una Expresión de una lambda compilada por IL, aunque no es terriblemente elegante. Aumento del ejemplo de Konrad:

// 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

Esto ** no ** le da el árbol de expresiones de la lamda original, le da un ** nuevo ** árbol de expresiones que llama al delegado. Nada mas. – Aidiakapi

+0

La pregunta no es específica sobre cómo obtener una expresión * equivalente *. Para LINQ en memoria esto proporciona una funcionalidad idéntica. Por supuesto, ningún proveedor de LINQ podría analizarlo correctamente. – joniba