Activator.CreateInstance Performance Alternative
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Activator.CreateInstance uses reflection to instantiate types at runtime, which is convenient but slow — roughly 5-50x slower than direct construction depending on the scenario. For hot paths in dependency injection containers, serializers, and object pools, this overhead matters. Faster alternatives include compiled lambda expressions, Expression.New, cached ConstructorInfo.Invoke, and source generators. Each approach trades compile-time knowledge for runtime flexibility at different performance levels.
Baseline: Activator.CreateInstance
Activator.CreateInstance locates the constructor via reflection on every call. There is no caching — each invocation pays the full reflection cost.
Alternative 1: Compiled Lambda Expression
The expression tree is compiled to IL once and cached. Subsequent calls invoke the compiled delegate directly — typically 10-50x faster than Activator.CreateInstance in benchmarks.
Alternative 2: Cached ConstructorInfo
Caching ConstructorInfo avoids the repeated type lookup but still uses reflection for the actual invocation. This is 2-5x faster than Activator.CreateInstance — a good middle ground when compiled expressions are too complex.
Alternative 3: Generic new() Constraint
The new() constraint lets the JIT compiler emit a direct constructor call. This is the fastest option but requires the type to be known at compile time through generics.
Performance Comparison
| Method | Relative Speed | Compile-Time Type Needed | Caching Required |
new T() | 1x (baseline) | Yes | No |
| Compiled Expression | ~1.2x | No (cached) | Yes |
| Cached ConstructorInfo | ~5x | No | Yes |
Activator.CreateInstance | ~25x | No | No |
Common Pitfalls
- Not caching the compiled delegate: Compiling an expression tree on every call is far slower than
Activator.CreateInstance. The speed benefit only comes from compiling once and reusing the cachedFunc<T>. Always store the compiled delegate in a static field orConcurrentDictionary. - Using
Activator.CreateInstancein hot loops: A single call toActivator.CreateInstanceis fast enough to be negligible, but calling it thousands of times per second (e.g., in a DI container or serializer) creates measurable overhead. Profile before optimizing — only switch to compiled expressions if profiling shows reflection as a bottleneck. - Forgetting thread safety for the cache: If multiple threads access the factory cache simultaneously, use
ConcurrentDictionaryinstead ofDictionary. A regular dictionary can corrupt its internal state under concurrent writes. - Ignoring constructor parameters:
Expression.New(typeof(T))only works for parameterless constructors. For types with constructor parameters, build the expression tree withExpression.New(constructorInfo, parameterExpressions)and match parameter types correctly. - Assuming
new T()with a generic constraint is always fast: Thenew()constraint generates a call toActivator.CreateInstance<T>()in some older .NET runtimes. In .NET 6+ the JIT optimizes this to a direct constructor call, but on .NET Framework it may still use reflection internally.
Summary
Activator.CreateInstanceis convenient but 10-50x slower than direct construction- Compiled lambda expressions (
Expression.New+.Compile()) are nearly as fast asnewwhen cached - Cache
ConstructorInfofor a simpler 2-5x speedup overActivator.CreateInstance - Use
new()generic constraints when the type is known at compile time - Always profile first — only optimize if reflection is a measured bottleneck
- Use
ConcurrentDictionaryfor thread-safe caching of compiled factories
Related reading
- actor critic policy loss going to zero with no improvement
- Adding bot turn costs to A search in pathfinding within a grid
- Adding regularizer to an existing layer of a trained model without resetting weights?
- Adjusting CommandTimeout in Dapper.NET?
- Add client certificate to .NET Core HttpClient
- Add new item in existing array in c.net
- Adjusting decimal precision, .net
- Advanced Banner-Rotation Algorithms

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.