Consider the following simple manipulation over a collection:
static List x = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var result
Recently I asked an almost identical question:
Performance of compiled-to-delegate Expression
The solution for me was that I shouldn't call Compile on the Expression, but that I should call CompileToMethod on it and compile the Expression to a static method in a dynamic assembly.
Like so:
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("MyAssembly_" + Guid.NewGuid().ToString("N")),
AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
var typeBuilder = moduleBuilder.DefineType("MyType_" + Guid.NewGuid().ToString("N"),
TypeAttributes.Public));
var methodBuilder = typeBuilder.DefineMethod("MyMethod",
MethodAttributes.Public | MethodAttributes.Static);
expression.CompileToMethod(methodBuilder);
var resultingType = typeBuilder.CreateType();
var function = Delegate.CreateDelegate(expression.Type,
resultingType.GetMethod("MyMethod"));
It's not ideal however. I'm not quite certain to which types this applies exactly, but I think that types that are taken as parameters by the delegate, or returned by the delegate have to be public and non-generic. It has to be non-generic because generic types apparently access System.__Canon which is an internal type used by .NET under the hood for generic types and this violates the "has to be a public type rule).
For those types, you can use the apparently slower Compile. I detect them in the following way:
private static bool IsPublicType(Type t)
{
if ((!t.IsPublic && !t.IsNestedPublic) || t.IsGenericType)
{
return false;
}
int lastIndex = t.FullName.LastIndexOf('+');
if (lastIndex > 0)
{
var containgTypeName = t.FullName.Substring(0, lastIndex);
var containingType = Type.GetType(containgTypeName + "," + t.Assembly);
if (containingType != null)
{
return containingType.IsPublic;
}
return false;
}
else
{
return t.IsPublic;
}
}
But like I said, this isn't ideal and I would still like to know why compiling a method to a dynamic assembly is sometimes an order of magnitude faster. And I say sometimes because I've also seen cases where an Expression compiled with Compile is just as fast as a normal method. See my question for that.
Or if someone knows a way to bypass the "no non-public types" constraint with the dynamic assembly, that's welcome as well.