2011-11-14 12 views
24

Estoy tratando de entender AST en C#. Me pregunto, qué método exactamente Compile() de este ejemplo hace.¿Qué hace el método Lambda Expression Compile()?

// Some code skipped  
Expression<Func<string, int, int, string>> data = Expression.Lambda<Func<string, int, int, string>>( 
     Expression.Call(s, typeof(string).GetMethod(“Substring”, new Type[] { typeof(int), typeof(int) }), a, b), 
     s, a, b 
    ); 
Func<string, int, int, string> fun = data.Compile(); 

Para evitar malentendidos, entiendo la Expression.Lambda y Expression.Call construcciones. Lo que me interesa es el método Compile(). ¿De alguna manera produce MSIL real? ¿Puedo ver el MSIL?

+0

Para pasar de una Expresión a un delegado puede invocar debe llamar a 'Compilar()' – BrokenGlass

+0

Ok, ¿y qué hay detrás de ese delegado? –

+0

Un método (MethodInfo) – Jeff

Respuesta

44

Lo que me interesa es el método Compile(). ¿De alguna manera produce MSIL real?

Sí. El método Compile ejecuta un visitante sobre el bloque corporal lambda y genera IL dinámicamente para cada subexpresión.

Si está interesado en aprender a escupir IL usted mismo, vea this "Hello World" example of how to use Lightweight Codegen. (Tengo en cuenta que si se encuentra en la desafortunada situación de tener que usar Lightweight Codegen en un dominio de aplicación parcialmente confiable, entonces las cosas pueden ponerse un poco raras en un mundo con visibilidad de omisión restringida; consulte Shawn Farkas's article sobre el tema si le interesa)

¿Puedo ver el MSIL?

Sí, pero necesita un "visualizador" especial. El visualizador que utiliza para depurar Compile() mientras yo estaba poniendo en práctica mis porciones de la misma puede ser descargada aquí:

http://blogs.msdn.com/b/haibo_luo/archive/2005/10/25/484861.aspx

+2

Muy impresionante, aunque me da un poco de dolor de cabeza. –

7

Una expresión representa una estructura de datos en forma de árbol de expresiones: utilizando Compile() este árbol de expresiones se puede compilar en código ejecutable en forma de delegado (que es una llamada de "método").

Después de la compilación, puede invocar normalmente al delegado; en su ejemplo, el delegado es un Func<string,int,int,string>. Este enfoque puede ser necesario cuando crea dinámicamente el árbol de expresiones basado en datos que solo están disponibles en tiempo de ejecución con el objetivo final de crear y ejecutar el delegado correspondiente.

No puede ver el "código" para el delegado. El árbol de expresiones en el que está basado es el más cercano a eso.

+0

Gracias! Lo que todavía no entiendo es cómo se puede ejecutar al delegado. Supongo que debe haber bytecode, en alguna parte ... –

+0

Quizás fuera del tema, pero me pregunto cuáles son las penalizaciones de rendimiento para generar todo este IL de forma dinámica. –

0

La respuesta a esto es ahora parte desfasado, en la que ahora es sólo a veces lo que sucede.

La compilación de expresiones en IL requiere Reflection.Emit que no está disponible todo el tiempo, especialmente con AOT. Entonces, en esos casos, en lugar de compilar para IL, la expresión se "compila" a una lista de objetos que representan instrucciones. Cada una de estas instrucciones tiene un método Run que hace que lleve a cabo la acción apropiada, trabajando en una pila de valores de manera similar a como IL trabaja en una pila. Un método que llama a Run en estos objetos puede ser devuelto como el delegado.

Generalmente ejecutar un delegado es más lento que jitting IL, pero es la única opción cuando compilar para IL no está disponible, y el paso de compilación suele ser más rápido, por lo que el tiempo total de compilación + ejecución es menor el intérprete que con IL para expresiones únicas.

Por esa razón, en.NET Core ahora tiene una sobrecarga de Compile que toma una interpretación de petición booleana incluso si está disponible la compilación a IL.

Todo lo cual lo convierte en una mezcla interesante de idiomas; Las expresiones en sí mismas son un lenguaje, el ensamblaje está escrito en C#, puede compilarse a IL y los objetos de instrucción interpretados constituyen un cuarto idioma.

Cuestiones relacionadas