Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Unusually if you really need this and don't mind throwing too much infrastructure at the problem, you can use <code>ldvirtftn</code> and <code>calli</code>.</p> <p>It seems very strange to me as that's what I thought was what a delegate did behind the scene basically do the following...</p> <pre><code>public class MyAction{ public virtual void Invoke(SomeClass @this) { ldarg.1 dup ldvirtftn SomeClass.GenericMethod&lt;Int32&gt; calli void *(argument) ret } </code></pre> <p><code>Ldvirtftn</code> does a look up to figure out the function pointer to be invoked for this particular method. If you use a non-virtual generic method the performance is about the same as a delegate bound to the same function. And if it is a virtual generic method its about twice as slow, that said its still works so that's quite an improvement.<br> I created this using reflection.emit and it seems to work just fine and it can invoke a closed virtual generic method. Unfortunately, unlike a delegate this type is bound to a specific method. However, quite a pain in the butt is that the runtime doesn't allow you to create a dynamic method that uses <code>ldvirtftn</code>,<code>ldftn</code>, or <code>calli</code> opcode. </p> <pre><code> public class SomeType { public virtual void DoNothing&lt;T&gt;() { Console.WriteLine(typeof(T)); } } public abstract class MyAction { public abstract void Invoke(SomeType type); } public static void Main(string[] args) { TypeBuilder builder = AppDomain.CurrentDomain .DefineDynamicAssembly(new AssemblyName(MethodBase.GetCurrentMethod().DeclaringType.Name), AssemblyBuilderAccess.RunAndCollect) .DefineDynamicModule("Module").DefineType("MyType", TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, typeof (MyAction)); var ilgen = builder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual, CallingConventions.HasThis, typeof (void), new[] {typeof (SomeType)}).GetILGenerator(); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Ldvirtftn, typeof (SomeType).GetMethod("DoNothing").MakeGenericMethod(typeof (int))); ilgen.Emit(OpCodes.Calli, SignatureHelper.GetMethodSigHelper(CallingConventions.HasThis, typeof (void))); ilgen.Emit(OpCodes.Ret); MyAction action = Activator.CreateInstance(builder.CreateType()) as MyAction; action.Invoke(new SomeType()); } </code></pre> <p>If you are okay with code generation you can use expression trees or dynamicmethod to just invoke the method. It's a little slower than a direct delegate but we're talking a tiny overhead. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload