Activator.CreateInstance
C# programming
.NET
reflection
code examples

Purpose of Activator.CreateInstance with example?

Master System Design with Codemia

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

Introduction

Activator.CreateInstance exists for one main reason: it lets .NET create an object when the type is known only at runtime. That makes it useful for reflection-based tools, plugin loading, configuration-driven factories, and frameworks that need to instantiate types dynamically.

The Basic Idea

Normally, object creation is static and explicit.

csharp
var person = new Person();

That works when the type is known at compile time. Activator.CreateInstance is for the opposite case: the program discovers the type later and still needs to build an instance.

csharp
1using System;
2
3class Person
4{
5    public string Name { get; set; } = "Ava";
6}
7
8class Program
9{
10    static void Main()
11    {
12        Type type = typeof(Person);
13        object instance = Activator.CreateInstance(type)!;
14        Console.WriteLine(instance.GetType().Name);
15    }
16}

The return type is object because the compiler cannot know the specific runtime type in advance.

Why Reflection-Based Code Uses It

Imagine a plugin system where the class name comes from configuration. The program can load the type and instantiate it dynamically.

csharp
1using System;
2
3interface ITask
4{
5    void Run();
6}
7
8class EmailTask : ITask
9{
10    public void Run() => Console.WriteLine("Sending email");
11}
12
13class Program
14{
15    static void Main()
16    {
17        Type type = typeof(EmailTask);
18        var task = (ITask)Activator.CreateInstance(type)!;
19        task.Run();
20    }
21}

This is the classic purpose: runtime flexibility when direct new is not possible.

Parameterized Constructors Also Work

Activator.CreateInstance can pass constructor arguments too.

csharp
1using System;
2
3class Person
4{
5    public string Name { get; }
6
7    public Person(string name)
8    {
9        Name = name;
10    }
11}
12
13class Program
14{
15    static void Main()
16    {
17        Type type = typeof(Person);
18        var person = (Person)Activator.CreateInstance(type, "Ava")!;
19        Console.WriteLine(person.Name);
20    }
21}

That makes it usable even when the runtime-selected type does not have a parameterless constructor.

Compare It to Generics and Dependency Injection

If the type is known at compile time, direct construction or dependency injection is often cleaner than reflection-based creation. Activator.CreateInstance is not the default object-creation tool for ordinary application code.

Use it when:

  • The type really is discovered at runtime.
  • Reflection is already part of the design.
  • A framework or plugin mechanism needs generic runtime instantiation.

Avoid it when a normal constructor call would be simpler and clearer.

Costs and Limitations

Because it relies on reflection, Activator.CreateInstance is generally slower and less explicit than direct construction. It also fails at runtime instead of compile time if:

  • The type does not have the expected constructor.
  • The constructor arguments do not match.
  • The type is abstract.
  • The type cannot be instantiated for accessibility or design reasons.

That is the tradeoff for flexibility.

Generic Overloads Exist Too

When the type is known generically but not through a direct constructor call, the generic Activator.CreateInstance<T>() overload can be more readable than the non-generic reflection form. The purpose is the same, but the call site is cleaner.

Common Pitfalls

  • Using Activator.CreateInstance where a normal constructor call would be simpler.
  • Forgetting to cast the returned object to the expected type.
  • Assuming a parameterless constructor exists when it does not.
  • Pushing too much application design into reflection instead of using clearer abstractions.
  • Treating runtime instantiation failures like compile-time-safe code paths.

Summary

  • 'Activator.CreateInstance is for creating objects when the concrete type is known only at runtime.'
  • It is commonly used in reflection-heavy, plugin-based, or framework code.
  • It can call parameterless or parameterized constructors.
  • The flexibility comes with runtime risk and some overhead.
  • If the type is already known at compile time, direct construction is usually the better choice.

Course illustration
Course illustration

All Rights Reserved.