Question
In C#, how can you call a generic method when the type argument is not known at compile time, but is instead determined dynamically at runtime?
For example, in the following code, the Example() method gets a Type object from FindType(typeName). What is the correct and concise way to call GenericMethod<T>() using the type stored in myType?
How would the approach differ for calling the static method StaticMethod<T>()?
public class Sample
{
public void Example(string typeName)
{
Type myType = FindType(typeName);
// How do we call GenericMethod<T>() here?
// GenericMethod<myType>(); // This does not compile
// How do we call StaticMethod<T>() here?
// Sample.StaticMethod<myType>(); // This also does not compile
}
public void GenericMethod<T>()
{
// ...
}
public static void StaticMethod<T>()
{
// ...
}
}
Short Answer
By the end of this page, you will understand why GenericMethod<myType>() does not compile in C#, and how to call a generic method when the type is only known at runtime. You will learn how to use reflection with GetMethod(), MakeGenericMethod(), and Invoke() for both instance and static generic methods, along with common mistakes and practical patterns used in real codebases.
Concept
In C#, generic type arguments such as T are normally chosen at compile time. That means code like this works:
GenericMethod<int>();
because int is a known type when the code is compiled.
But this does not work:
Type myType = typeof(int);
GenericMethod<myType>();
The reason is that myType is a variable, not a type name in source code. C# generic syntax requires an actual type at compile time, not a Type object stored in memory.
When the type is only available at runtime, the usual solution is reflection.
The key reflection steps are:
- Find the generic method definition.
- Create a closed generic version of that method using
MakeGenericMethod(runtimeType). - Invoke the method.
Example idea:
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(this, null);
This matters in real programs because runtime-selected types appear often:
Mental Model
Think of a generic method like a template machine.
GenericMethod<int>()means: “build the machine configured forint.”GenericMethod<string>()means: “build the machine configured forstring.”
At compile time, C# wants you to say exactly which machine you want.
A Type variable is more like a note in your hand that says which machine to build later. The compiler cannot use that note directly in generic syntax. Instead, reflection acts like a factory worker who reads the note at runtime and builds the correct version of the machine for you.
So:
- generic syntax (
<int>) = compile-time choice Typeobject (typeof(int)or runtime result) = runtime choice- reflection = bridge between the two
Syntax and Examples
Core syntax
To call a generic method using a runtime Type in C#, use reflection:
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(this, null);
For a static generic method:
MethodInfo method = typeof(Sample).GetMethod(nameof(StaticMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(null, null);
Complete example
using System;
using System.Reflection;
public class Sample
{
public void Example(string typeName)
{
Type myType = FindType(typeName);
MethodInfo instanceMethod = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedInstanceMethod = instanceMethod.MakeGenericMethod(myType);
closedInstanceMethod.Invoke(this, null);
MethodInfo staticMethod = typeof(Sample).GetMethod((StaticMethod));
MethodInfo closedStaticMethod = staticMethod.MakeGenericMethod(myType);
closedStaticMethod.Invoke(, );
}
{
Console.WriteLine();
}
{
Console.WriteLine();
}
{
typeName
{
=> (),
=> (),
_ => ()
};
}
}
Step by Step Execution
Traceable example
using System;
using System.Reflection;
public class Sample
{
public void Example()
{
Type myType = typeof(string);
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closedMethod = method.MakeGenericMethod(myType);
closedMethod.Invoke(this, null);
}
public void GenericMethod<T>()
{
Console.WriteLine(typeof(T).FullName);
}
}
Step by step
1. myType is assigned
Type myType = typeof(string);
Now myType stores the runtime type System.String.
2. The generic method definition is found
MethodInfo method = (Sample).GetMethod((GenericMethod));
Real World Use Cases
Where this is used
Serializers
A serializer may discover the target type at runtime and need to call a generic method like:
Deserialize<T>()
Dependency injection containers
A DI framework may resolve services from a Type object and internally build calls to generic methods such as:
Resolve<T>()
Mapping libraries
Object mappers often receive source and destination types dynamically and may call generic conversion methods behind the scenes.
Plugin systems
A plugin loader might inspect assemblies, find types, and invoke generic registration methods based on discovered classes.
Data access helpers
A repository may need to call methods like:
GetEntity<T>()
when T comes from configuration, metadata, or reflection.
Testing tools and frameworks
Unit testing frameworks often discover test classes and invoke generic helper methods using runtime type information.
Real Codebase Usage
Common patterns in real projects
Guard clauses before reflection
Reflection can fail if the method is not found or the type is invalid. Real code often validates early:
if (myType == null)
throw new ArgumentNullException(nameof(myType));
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod))
?? throw new InvalidOperationException("Method not found.");
Caching MethodInfo
Reflection is slower than direct calls. In production code, developers often cache method metadata:
private static readonly MethodInfo GenericMethodDefinition =
typeof(Sample).GetMethod(nameof(GenericMethod));
Then reuse it instead of calling GetMethod() repeatedly.
Wrapping reflection in helper methods
Teams usually avoid scattering reflection code everywhere. Instead, they create a helper:
public void ()
{
MethodInfo method = (Sample).GetMethod((GenericMethod));
MethodInfo closed = method.MakeGenericMethod(type);
closed.Invoke(, );
}
Common Mistakes
1. Trying to use a Type variable in generic syntax
This does not compile:
Type myType = typeof(int);
GenericMethod<myType>();
Why
Generic angle-bracket syntax expects a compile-time type, not a variable.
Fix
Use reflection:
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(this, null);
2. Passing the wrong target to Invoke()
Broken code for an instance method:
closedMethod.Invoke(null, null);
Why
Instance methods need an object instance.
Fix
Use this or another object instance:
closedMethod.Invoke(this, null);
For static methods, is correct.
Comparisons
Generic call at compile time vs runtime
| Approach | When it works | Example | Pros | Cons |
|---|---|---|---|---|
| Direct generic call | Type is known at compile time | GenericMethod<int>() | Fast, simple, type-safe | Cannot use runtime Type values |
Reflection with MakeGenericMethod | Type is only known at runtime | method.MakeGenericMethod(myType).Invoke(...) | Flexible, works with dynamic type discovery | More verbose, less type-safe, slower |
Instance vs static generic method invocation
| Method kind | Target passed to Invoke() |
|---|
Cheat Sheet
Quick reference
Direct generic call
GenericMethod<int>();
Use this when the type is known at compile time.
Runtime generic call
MethodInfo method = typeof(Sample).GetMethod(nameof(GenericMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(this, null);
Static runtime generic call
MethodInfo method = typeof(Sample).GetMethod(nameof(StaticMethod));
MethodInfo closed = method.MakeGenericMethod(myType);
closed.Invoke(null, null);
Rules
GenericMethod<myType>()is invalid becausemyTypeis a variable, not a compile-time type.- Use
MakeGenericMethod()for generic methods. - Use
MakeGenericType()for generic classes/types. - Pass an object instance to
Invoke()for instance methods. - Pass
nulltoInvoke()for static methods.
FAQ
How do I call a generic method when I only have a Type object in C#?
Use reflection: find the method with GetMethod(), create a closed generic method with MakeGenericMethod(type), then call Invoke().
Why does GenericMethod<myType>() not compile?
Because C# generic syntax requires a type known at compile time. myType is a variable holding a Type value at runtime.
How do I invoke a static generic method with reflection?
Use the same reflection steps, but pass null as the target in Invoke().
What is the difference between MakeGenericMethod and MakeGenericType?
MakeGenericMethod is for generic methods. MakeGenericType is for generic classes or other generic types.
Is reflection the only way to do this?
If the type is truly unknown until runtime, reflection is the standard approach. If the possible types are known ahead of time, a switch, delegate map, or polymorphic design may be better.
Mini Project
Description
Build a small runtime type invoker that accepts a type name like "int", "string", or "DateTime", converts it into a Type, and then calls both an instance generic method and a static generic method using that runtime type. This demonstrates the exact reflection pattern used when generic arguments are discovered dynamically.
Goal
Create a C# class that finds a runtime type from a string and invokes ShowType<T>() and ShowStaticType<T>() using reflection.
Requirements
- Create a method that converts a type name string into a
Type. - Add one instance generic method and one static generic method.
- Use reflection to call both methods with the runtime type.
- Print the selected type name from inside each generic method.
- Handle the case where the type name is unknown.
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.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.