¿Qué hace el método Compile() de la expresión Lambda?


Estoy tratando de entender AST en C#. Me pregunto qué hace exactamente el método Compile() de este ejemplo.

// 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 las construcciones Expression.Lambda y Expression.Call. Lo que me interesa es el método Compile(). ¿De alguna manera produce MSIL real? ¿Puedo ver el MSIL?

Author: jk_, 2011-11-14

3 answers

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 lambda body y genera IL dinámicamente para cada subexpresión.

Si usted está interesado en aprender a escupir IL usted mismo, vea este ejemplo de "Hola Mundo" de cómo usar Lightweight Codegen. (Observo que si estás en la desafortunada posición de tener que usar Lightweight Codegen en un appdomain parcialmente confiable entonces las cosas pueden ponerse un poco raras en un mundo con Visibilidad de Salto Restringida; vea El artículo de Shawn Farkas sobre el tema si eso le interesa.)

¿Puedo ver el MSIL?

Sí, pero necesita un "visualizador"especial. El visualizador que utilicé para depurar Compile() mientras estaba implementando mis partes se puede descargar aquí:

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

 47
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-14 20:06:10

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

Después de la compilación, normalmente puede invocar al delegado - en su ejemplo, el delegado es un Func<string,int,int,string>. Este enfoque puede ser necesario cuando se 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 ejecución del delegado correspondiente.

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

 8
Author: BrokenGlass,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-14 19:41:08

La respuesta a esto está ahora en parte anticuada, ya que ahora es solo a veces lo que sucede.

La compilación de expresiones a IL requiere Reflexión.Emitir que no está disponible todo el tiempo, en particular con AOT. Así que en esos casos en lugar de compilar a IL la expresión es "compilada" 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 adecuada, trabajando en una pila de valores tanto como IL trabaja en una pila. Un método que llame a Run en estos objetos puede devolverse como delegado.

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

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

Todo lo cual hace una interesante mezcla de lenguajes; las expresiones en sí mismas son un lenguaje, el ensamblado está escrito en C#, puede compilar a IL y los objetos de instrucción interpretados constituyen un cuarto lenguaje.

 5
Author: Jon Hanna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-03 22:18:54