Question
In C#, you may not always know an object's type at compile time, but you may still need to create an instance of that type at runtime.
How can you create a new object instance when all you have is a Type?
For example, the goal is to create an instance dynamically from something like:
Type type = /* some runtime type */;
and then produce a new object of that type.
Short Answer
By the end of this page, you will understand how to create objects dynamically in C# when you only have a Type at runtime. You will learn the most common approach using Activator.CreateInstance, how constructors affect object creation, when reflection is useful, and what mistakes to avoid when instantiating types dynamically.
Concept
In normal C# code, object creation usually happens with the new keyword:
var user = new User();
That works when the type is known at compile time. But sometimes a program discovers the type later, while it is running. This happens in scenarios like:
- plugin systems
- dependency injection containers
- serializers
- configuration-driven object creation
- test frameworks
When all you have is a Type object, you cannot write:
new type(); // invalid
because new requires a compile-time type name, not a runtime Type value.
This is where Activator.CreateInstance becomes useful. It lets you ask the runtime to create an object from a Type.
object instance = Activator.CreateInstance(type);
This creates a new instance of the specified type, usually by calling its parameterless constructor.
Why this matters:
- It allows flexible, extensible programs.
- It supports runtime discovery of classes.
Mental Model
Think of Type as a blueprint label, not the actual building.
new User()means: "Build me a house from theUserblueprint I already know."Type type = ...means: "Here is a label that tells you which blueprint to use, but you only find out at runtime."Activator.CreateInstance(type)means: "Use this blueprint label and build one instance now."
So Type tells you what something is, and Activator.CreateInstance is the worker that actually builds it.
Syntax and Examples
Basic syntax
object instance = Activator.CreateInstance(type);
This returns an object, because the compiler may not know the exact type.
Example with a parameterless constructor
using System;
class Person
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
Person person = (Person)instance;
person.Name = "Ava";
Console.WriteLine(person.Name);
}
}
What this does
typeof(Person)gets the runtimeType.Activator.CreateInstance(type)creates a newPerson.- The result is returned as
object. - You cast it back to
Personif needed.
Step by Step Execution
Consider this example:
using System;
class Message
{
public string Text { get; set; } = "Hello";
}
class Program
{
static void Main()
{
Type type = typeof(Message);
object instance = Activator.CreateInstance(type);
Message message = (Message)instance;
Console.WriteLine(message.Text);
}
}
Step by step
-
Type type = typeof(Message);- The program gets metadata describing the
Messageclass. - No object is created yet.
- The program gets metadata describing the
-
object instance = Activator.CreateInstance(type);- The runtime checks the
Messagetype. - It finds a usable parameterless constructor.
- It creates a new
Messageobject. - The result is stored as
object.
- The runtime checks the
Real World Use Cases
Plugin systems
An app may load class names from assemblies and create plugin objects dynamically.
Type pluginType = loadedAssembly.GetType("MyApp.Plugins.CsvExporter");
object plugin = Activator.CreateInstance(pluginType);
Configuration-based services
A configuration file may specify which implementation to use.
EmailSenderSmsSenderPushNotificationSender
The application resolves the type at runtime and creates it.
Testing frameworks
Test runners often discover test classes through reflection and instantiate them automatically.
Serialization and mapping tools
Libraries may create objects before populating their properties from JSON, XML, or database records.
Command or job processors
A background worker may discover a job type from a queue message and instantiate the appropriate handler.
Real Codebase Usage
In real projects, developers usually combine runtime object creation with safer design patterns.
Common patterns
Create via interface or base class
Instead of using the created object as plain object, cast to a known abstraction:
IPlugin plugin = (IPlugin)Activator.CreateInstance(type);
plugin.Run();
This makes the rest of the code cleaner and safer.
Guard clauses before creation
Real code often validates the type first:
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type.IsAbstract || type.IsInterface)
throw new InvalidOperationException("Type cannot be instantiated.");
Constructor matching
If arguments are needed, code ensures the right constructor exists.
object service = Activator.CreateInstance(type, connectionString);
Error handling
Because dynamic creation can fail at runtime, developers often wrap it:
try
{
Activator.CreateInstance(type);
}
(Exception ex)
{
InvalidOperationException(, ex);
}
Common Mistakes
1. Trying to use new with a Type
Broken code:
Type type = typeof(string);
// var x = new type(); // invalid
Why it fails:
newneeds a real type name at compile time.typeis just a variable holding metadata.
Use this instead:
object x = Activator.CreateInstance(type);
2. Assuming every type has a parameterless constructor
Broken code:
class Person
{
public Person(string name) { }
}
Type type = typeof(Person);
object instance = Activator.CreateInstance(type); // fails
Fix:
object instance = Activator.CreateInstance(type, "Mia");
Comparisons
| Approach | When to use | Pros | Cons |
|---|---|---|---|
new MyClass() | Type known at compile time | Fast, safe, simple | Not dynamic |
Activator.CreateInstance(type) | Type known only at runtime | Flexible, built into .NET | Runtime errors possible |
Activator.CreateInstance(type, args) | Runtime type with constructor parameters | Can call matching constructors | More fragile if arguments do not match |
Generic new() constraint | Generic code with parameterless constructor | Compile-time safety | Only works for parameterless constructors |
| Factory method | Known set of types |
Cheat Sheet
Quick reference
Create an instance from a Type
object instance = Activator.CreateInstance(type);
Create with constructor arguments
object instance = Activator.CreateInstance(type, arg1, arg2);
Generic version
T instance = Activator.CreateInstance<T>();
Rules to remember
new SomeType()works only when the type is known at compile time.Activator.CreateInstanceworks when the type is known only at runtime.- The return type is usually
object. - Cast the result to a known interface, base class, or concrete type.
- The target type must be instantiable.
Common checks
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type.IsInterface || type.IsAbstract)
throw new InvalidOperationException();
FAQ
How do I create an instance from a Type in C#?
Use Activator.CreateInstance(type). It asks the runtime to create an object for that Type.
Can I use new with a Type variable?
No. The new keyword requires a compile-time type name, not a runtime Type value.
What happens if the type has no default constructor?
You must pass matching constructor arguments, for example:
Activator.CreateInstance(type, "value")
Why does Activator.CreateInstance return object?
Because the compiler may not know the specific type in advance. You usually cast it to a known type, interface, or base class.
Can I create interfaces or abstract classes this way?
No. Interfaces and abstract classes cannot be instantiated directly.
Is Activator.CreateInstance slower than new?
Yes, generally it is slower because it uses runtime mechanisms. For most normal code, prefer when possible.
Mini Project
Description
Build a small runtime object factory in C#. The program should accept a Type, create an instance if possible, and print information about the created object. This demonstrates practical use of Activator.CreateInstance, type validation, and safe casting.
Goal
Create a reusable method that instantiates valid runtime types and rejects types that cannot be created.
Requirements
- Create at least two sample classes that can be instantiated.
- Add one type that cannot be instantiated directly, such as an abstract class or interface.
- Write a method that accepts a
Typeand returns a new object instance. - Validate the type before instantiating it.
- Print success or error messages for each test type.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.