Curiosity did get the better of me so I ended up benchmarking it myself. I still recommend doing it yourself to give it a go and see if you get the same results. If you had a specific situation in mind that might yield different results.
Results
I was kind of surprised at first, but here they are. I added in a standard Delegate.Invoke
just to compare.
Method |
Mean |
Error |
StdDev |
Gen 0 |
Gen 1 |
Gen 2 |
Allocated |
MethodInfoInvoke |
116.9913 ns |
1.0848 ns |
1.0148 ns |
0.0024 |
- |
- |
40 B |
DelegateDynamicInvoke |
391.8141 ns |
6.6877 ns |
6.2557 ns |
0.0105 |
- |
- |
176 B |
DelegateInvoke |
0.4334 ns |
0.0037 ns |
0.0033 ns |
- |
- |
- |
- |
As you can see, MethodInfo.Invoke
is much better than Delegate.DynamicInvoke
.
This is without considering the cost of converting the MethodInfo
into a Delegate
in the first place. Also the MethodInfo
can just be used on any instance, whereas Delegate.DynamicInvoke
is locked to a specific instance (Could be wrong on that though, I haven't used CreateDelegate
before).
And lastly you need to pass the delegate type to CreateDelegate
, which wouldn't always be easy.
So for less work, you get faster invocation and less garbage generated by using MethodInfo.Invoke
.
Benchmark Code
[MemoryDiagnoser]
public class Benchmark
{
private MethodInfo MethodInfo { get; set; }
private Delegate MethodDynamicDelegate { get; set; }
private Action<int, string> MethodDelegate { get; set; }
private object[] Params { get; } = new object[] { 0, "Param2" };
[GlobalSetup]
public void Setup()
{
this.MethodInfo = typeof(Benchmark).GetMethod(nameof(TestMethod));
this.MethodDynamicDelegate = Delegate.CreateDelegate(typeof(Action<int, string>), this, this.MethodInfo);
this.MethodDelegate = this.TestMethod;
}
[Benchmark]
public void MethodInfoInvoke()
{
this.MethodInfo.Invoke(this, this.Params);
}
[Benchmark]
public void DelegateDynamicInvoke()
{
this.MethodDynamicDelegate.DynamicInvoke(this.Params);
}
[Benchmark]
public void DelegateInvoke()
{
this.MethodDelegate.Invoke(0, "Param2");
}
public void TestMethod(int param1, string param2)
{
}
}