.NET
reflection
performance
cost analysis
software development

How costly is .NET reflection?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

.NET reflection is extremely useful for metadata inspection, plugin systems, and framework infrastructure, but it has real runtime overhead compared with direct typed access. The cost depends less on whether reflection exists and more on where it is used. Reflection in startup paths is often fine, while reflection inside hot loops can be expensive.

Where Reflection Overhead Comes From

Reflection performs work that direct calls avoid:

  • metadata lookup for members
  • access checks and boxing operations
  • argument array creation for Invoke
  • dynamic dispatch instead of JIT-inlined direct calls

A single call may be negligible. Repeating that work millions of times is where cost becomes visible.

Baseline Example: Direct Call vs Reflection Invoke

A small benchmark illustrates relative cost.

csharp
1using System;
2using System.Diagnostics;
3using System.Reflection;
4
5public class Worker
6{
7    public int AddOne(int x) => x + 1;
8}
9
10public class Program
11{
12    public static void Main()
13    {
14        var worker = new Worker();
15        const int loops = 1_000_000;
16
17        var sw = Stopwatch.StartNew();
18        int direct = 0;
19        for (int i = 0; i < loops; i++)
20            direct = worker.AddOne(direct);
21        sw.Stop();
22        Console.WriteLine($"Direct: {sw.ElapsedMilliseconds} ms");
23
24        MethodInfo mi = typeof(Worker).GetMethod(nameof(Worker.AddOne))!;
25        sw.Restart();
26        int refl = 0;
27        for (int i = 0; i < loops; i++)
28            refl = (int)mi.Invoke(worker, new object[] { refl })!;
29        sw.Stop();
30        Console.WriteLine($"Reflection Invoke: {sw.ElapsedMilliseconds} ms");
31    }
32}

Exact timings vary by runtime and hardware, but reflective invocation is typically much slower.

Reflection Is Often Fine in Startup Paths

Not all reflection is a problem. Many frameworks use reflection at startup for:

  • dependency registration
  • attribute scanning
  • endpoint discovery
  • serialization contract setup

If this runs once and is cached, impact is usually acceptable.

Optimize Repeated Reflection with Caching

The biggest win is avoiding repeated lookup and invocation mechanics.

csharp
1using System;
2using System.Reflection;
3
4public class Worker
5{
6    public int AddOne(int x) => x + 1;
7}
8
9public class Demo
10{
11    public static void Main()
12    {
13        MethodInfo mi = typeof(Worker).GetMethod(nameof(Worker.AddOne))!;
14        var fast = (Func<Worker, int, int>)Delegate.CreateDelegate(
15            typeof(Func<Worker, int, int>),
16            mi
17        );
18
19        var w = new Worker();
20        Console.WriteLine(fast(w, 41));
21    }
22}

Here reflection is used once for discovery, then delegate invocation handles hot path calls.

Practical Heuristics for Production Systems

Use reflection directly when:

  • operation happens rarely
  • code simplicity matters more than micro-optimization
  • path is not latency-sensitive

Avoid direct reflection invocation in:

  • per-request API hot paths
  • per-row ETL loops
  • inner simulation loops

If unsure, profile with realistic data before rewriting code.

Alternatives to Reflection in Performance-Critical Paths

When profiling shows reflection bottlenecks, consider:

  • precompiled delegates
  • expression trees compiled once
  • source generators for static access code
  • explicit interfaces for known type sets

Each approach trades flexibility for speed. Pick based on measured bottlenecks and maintenance budget.

Measuring Correctly

Microbenchmarks can mislead if not representative. Benchmark guidance:

  • warm up runtime before measuring
  • include realistic object counts and payload sizes
  • compare end-to-end request impact, not only isolated method calls
  • measure allocations as well as CPU time

For .NET projects, BenchmarkDotNet is usually the safest benchmark framework.

Reflection and Maintainability Tradeoff

Reflection often reduces boilerplate and enables extensibility. Over-optimizing too early can produce rigid code that is harder to evolve. For many systems, moderate reflection plus caching gives the best balance between flexibility and speed.

Document reflective hotspots and rationale so future maintainers understand whether optimization is still justified.

Common Pitfalls

  • Assuming all reflection use is too slow without profiling.
  • Performing GetMethod and Invoke inside tight loops.
  • Ignoring allocation overhead from repeated argument array creation.
  • Over-optimizing startup reflection that runs once.
  • Replacing reflection with complex code that hurts maintainability without measurable gain.

Summary

  • Reflection has overhead, especially for repeated dynamic invocation.
  • Startup-time reflection is usually acceptable in many applications.
  • Cache metadata and use delegates for hot paths.
  • Optimize based on real profiling data, not assumptions.
  • Balance performance goals with maintainability and API flexibility.

Course illustration
Course illustration

All Rights Reserved.