MethodInfo Invocation Overhead vs Compiled Expressions / Delegates
1Concept
Calling `MethodInfo.Invoke()` requires parameter array allocation (`object[]`), boxing, and security checks (~150ns). Compiling a `Delegate.CreateDelegate` or `Expression.Compile` reduces invocation overhead to ~1ns.
2Architecture Diagram
Direct Method Call: 0.3 ns (Native Speed) Compiled Delegate / Emit: 1.2 ns (Near Native Speed) MethodInfo.Invoke (Reflection): 150.0 ns (100x Slower + Heap Boxing Allocations!)
3Code Example
C# 13 & .NET 9
using System;
using System.Reflection;
public class TargetService
{
public int Multiply(int a, int b) => a * b;
}
public class FastDelegateDemo
{
public static void Main()
{
var instance = new TargetService();
MethodInfo method = typeof(TargetService).GetMethod("Multiply")!;
// Convert MethodInfo to strongly-typed fast delegate!
var fastFunc = (Func<int, int, int>)Delegate.CreateDelegate(typeof(Func<int, int, int>), instance, method);
int result = fastFunc(6, 7);
Console.WriteLine($"Fast Delegate Invocation Result: {result} (Near Native Speed)");
}
}4Expected Output
Fast Delegate Invocation Result: 42 (Near Native Speed)
5Key Takeaways
- ✓Never call `MethodInfo.Invoke` repeatedly inside loops.
- ✓Use `Delegate.CreateDelegate` when the method signature is known at compile time.
- ✓Use `System.Linq.Expressions` or Source Generators when signatures vary dynamically.