.net - In C#, Is Expression API better than Reflection -


nowadays, i'm exploring c# expression apis. use understanding how works, including difference between expression , reflection. want understand if expressions merely syntactic sugar, or indeed better reflection performance-wise?

good examples links articles appreciated. :-)

regarding calling 1 method :

  • direct call can't beaten speed-wise.
  • using expression api globally similar using reflection.emit or delegate.createdelegate speed-wise (small differences measured; optimizing speed without measurements , goals useless).

    they generate il , framework compile native code @ point. still pay cost of 1 indirection level calling delegate , 1 method call inside delegate.

    the expression api more limited, order of magnitude simpler use, doesn't require learn il.

  • the dynamic language runtime either used directly or via dynamic keyword of c# 4 add little overhead stay near emitting code cache checks related parameter types, access , rest.

    when used via dynamic keyword it's neatest syntax looks normal method call. if use dynamic limited method calls while library able lot more (see ironpython)

  • system.reflection.methodinfo.invoke slow : in addition other methods need check access rights, check arguments count, type, ... against methodinfo each time call method.

jon skeet points in answer : delegate.createdelegate vs dynamicmethod vs expression


some samples, same thing done different ways.

you see line count , complexity solutions easy maintain , should avoided long term maintenance standpoint.

most of samples pointless demonstrate basic code generation classes / syntaxes of c#, more info there msdn

ps: dump linqpad method.

public class foo {     public string bar(int value) { return value.tostring(); } }  void main() {     object foo = new foo();      // have instance of , want call method signature on :     // public string bar(int value);      console.writeline("cast , direct method call");     {         var result = ((foo)foo).bar(42);         result.dump();     }     console.writeline("create lambda closing on local scope.");     {         // useless i'll @ end manual il generation          func<int, string> func = => ((foo)foo).bar(i);         var result = func(42);         result.dump();     }     console.writeline("using methodinfo.invoke");     {         var method = foo.gettype().getmethod("bar");         var result = (string)method.invoke(foo, new object[] { 42 });         result.dump();     }     console.writeline("using dynamic keyword");     {         var dynamicfoo = (dynamic)foo;         var result = (string)dynamicfoo.bar(42);         result.dump();     }     console.writeline("using createdelegate");     {         var method = foo.gettype().getmethod("bar");         var func = (func<int, string>)delegate.createdelegate(typeof(func<int, string>), foo, method);         var result = func(42);         result.dump();     }     console.writeline("create expression , compile call delegate on 1 instance.");     {         var method = foo.gettype().getmethod("bar");         var thisparam = expression.constant(foo);         var valueparam = expression.parameter(typeof(int), "value");         var call = expression.call(thisparam, method, valueparam);         var lambda = expression.lambda<func<int, string>>(call, valueparam);         var func = lambda.compile();         var result = func(42);         result.dump();     }     console.writeline("create expression , compile delegate called on instance.");     {         // note in case "foo" must known @ compile time, in case want         // more call method, otherwise call !         var type = foo.gettype();         var method = type.getmethod("bar");         var thisparam = expression.parameter(type, "this");         var valueparam = expression.parameter(typeof(int), "value");         var call = expression.call(thisparam, method, valueparam);         var lambda = expression.lambda<func<foo, int, string>>(call, thisparam, valueparam);         var func = lambda.compile();         var result = func((foo)foo, 42);         result.dump();     }     console.writeline("create dynamicmethod , compile delegate called on instance.");     {         // same thing previous expression sample. foo need known @ compile time , need         // provided delegate.          var type = foo.gettype();         var method = type.getmethod("bar");          var dynamicmethod = new dynamicmethod("bar_", typeof(string), new [] { typeof(foo), typeof(int) }, true);         var il = dynamicmethod.getilgenerator();         il.declarelocal(typeof(string));         il.emit(opcodes.ldarg_0);         il.emit(opcodes.ldarg_1);         il.emit(opcodes.call, method);         il.emit(opcodes.ret);         var func = (func<foo, int, string>)dynamicmethod.createdelegate(typeof(func<foo, int, string>));         var result = func((foo)foo, 42);         result.dump();     }     console.writeline("simulate closure without closures , in lot more lines...");     {         var type = foo.gettype();         var method = type.getmethod("bar");          // foo class must public work, "skipvisibility" argument of         // dynamicmethod.createdelegate can't emulated without breaking .net security model.          var assembly = appdomain.currentdomain.definedynamicassembly(             new assemblyname("myassembly"), assemblybuilderaccess.run);         var module = assembly.definedynamicmodule("mymodule");         var tb = module.definetype("mytype", typeattributes.class | typeattributes.public);          var foofield = tb.definefield("fooinstance", type, fieldattributes.public);         var barmethod = tb.definemethod("bar_", methodattributes.public, typeof(string), new [] { typeof(int) });         var il = barmethod.getilgenerator();         il.declarelocal(typeof(string));         il.emit(opcodes.ldarg_0); //         il.emit(opcodes.ldfld, foofield);         il.emit(opcodes.ldarg_1); // arg         il.emit(opcodes.call, method);         il.emit(opcodes.ret);          var closuretype = tb.createtype();          var instance = closuretype.getconstructors().single().invoke(new object[0]);          closuretype.getfield(foofield.name).setvalue(instance, foo);          var methodonclosuretype = closuretype.getmethod("bar_");          var func = (func<int, string>)delegate.createdelegate(typeof(func<int, string>), instance,             closuretype.getmethod("bar_"));         var result = func(42);         result.dump();     } } 

Comments

Popular posts from this blog

java - SNMP4J General Variable Binding Error -

windows - Python Service Installation - "Could not find PythonClass entry" -

Determine if a XmlNode is empty or null in C#? -