The new Compile(bool)
overload may make this clearer if you take a look, though the docs don't (currently) give much info on the details.
Compile()
used to always do IL-generation, and was hence not available with AOT.
For some time now (I forget when it came in) Compile()
can now also do "compilation" to a set of objects representing operations (they operate quite similarly to IL, with a stack represented by a fixed-length object[]
), which uses reflection (but not `Reflection.Emit' reflection) for method calls and its own code for basic operations like arithmetic.
Compile(bool)
let's you ask for IL-generation (false) or interpretation (true), but it's treated as a preference rather than a demand; if you ask for IL-generation on a platform that only has interpretation, you get interpretation, and vice versa. Mostly if you can do either you want IL generation (generally faster, and there's a few limitations on the interpreter) but you might want to rule out there being differences between platform, or you might find that while on average the interpreted delegates are slower to execute, on average the Compile()
step itself is faster with the interpreter and sometimes if you are creating several one-off expressions the total time is faster with the interpreter. (But not always, if you try this for performance reasons, profile and/or consider caching delegates if you can).
This incidentally means that System.Linq.Expressions
contains code representing one language (expressions are a sort of language in themselves), written in a second (C#), which are not only compiled into a third language (CIL) but also into yet another language (since the internal structures for interpretation are yet another language of sorts) which it contains an interpreter for. This is a big part of why I find it a fun project to contribute to :)