Dynamic Types in C#
Vaibhav • September 11, 2025
In previous chapters, we’ve worked extensively with statically typed variables - where the type of a variable is known at compile time and enforced by the compiler. This is one of C#’s core strengths: it helps catch errors early and makes your code predictable. But what if you need more flexibility? What if the type of a value isn’t known until runtime, or you’re working with loosely typed data like JSON, COM objects, or scripting APIs? That’s where dynamic types come in.
The dynamic
keyword in C# allows you to defer type checking until runtime. It
gives you the freedom to write flexible code that adapts to different types - while still staying within the C#
language. In this article, we’ll explore what dynamic types are, how they work, when to use them, and how to
avoid common pitfalls. We’ll build on your understanding of variables, methods, and object-oriented programming
- and introduce new patterns that unlock powerful scenarios.
What Is a Dynamic Type?
A dynamic type is a variable whose type is resolved at runtime - not at compile time. You declare it using the
dynamic
keyword:
dynamic value = 10;
Console.WriteLine(value); // Output: 10
value = "Hello";
Console.WriteLine(value); // Output: Hello
In this example, value
starts as an integer, then becomes a string. The
compiler doesn’t enforce type rules - it trusts that the operations will succeed at runtime. If they don’t,
you’ll get a runtime exception.
A dynamic
variable behaves like an object, but with
late binding. The compiler skips type checking, and the runtime resolves method calls, property access, and
conversions dynamically.
How Dynamic Differs from Object
You might wonder: how is dynamic
different from object
? Both can hold any type - but they behave differently:
object obj = "Vaibhav";
Console.WriteLine(obj.Length); // ❌ Compile-time error
dynamic dyn = "Vaibhav";
Console.WriteLine(dyn.Length); // ✅ Runtime success
With object
, you must cast to the correct type before accessing members. With
dynamic
, you can access members directly - and the runtime will resolve them.
This makes dynamic
more convenient for loosely typed scenarios.
Using Dynamic with Methods
You can pass dynamic values to methods, return them, and store them in variables. The compiler treats them as valid - but defers type resolution until runtime:
public dynamic Echo(dynamic input)
{
return input;
}
dynamic result = Echo(42);
Console.WriteLine(result); // Output: 42
result = Echo("Hello");
Console.WriteLine(result); // Output: Hello
This flexibility is useful when building generic utilities, scripting interfaces, or working with external data sources.
Dynamic and Runtime Errors
Because dynamic types skip compile-time checks, you must be careful. If you call a method or access a property that doesn’t exist, you’ll get a runtime exception:
dynamic user = "Vaibhav";
Console.WriteLine(user.FullName); // ❌ Runtime error: 'string' does not contain 'FullName'
The compiler won’t warn you - it assumes you know what you’re doing. This makes dynamic powerful, but also risky. Always validate your assumptions and test thoroughly.
Note: Use dynamic only when necessary. Prefer static typing for safety and performance. Dynamic is best for interop, scripting, and loosely typed data - not general-purpose programming.
Working with ExpandoObject
The ExpandoObject
class in System.Dynamic
lets
you create dynamic objects with runtime-defined properties. This is useful for building flexible data
structures:
using System.Dynamic;
dynamic person = new ExpandoObject();
person.Name = "Vaibhav";
person.Age = 30;
Console.WriteLine(person.Name); // Output: Vaibhav
Console.WriteLine(person.Age); // Output: 30
You can add or remove properties at runtime - making ExpandoObject
ideal for
scenarios like JSON parsing, scripting, or dynamic UI models.
Using Dynamic with JSON and External Data
Dynamic types are often used when working with JSON, XML, or other external data formats. For example, when deserializing JSON into a dynamic object:
using System.Text.Json;
string json = "{ \"Name\": \"Vaibhav\", \"Age\": 30 }";
dynamic user = JsonSerializer.Deserialize<dynamic>(json);
Console.WriteLine(user.Name); // Output: Vaibhav
This lets you work with data without defining a class upfront. It’s convenient - but you lose compile-time safety, so be cautious.
Interop with COM and Reflection
Dynamic types are essential when working with COM objects or reflection. For example, when automating Excel or Word:
dynamic excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
excel.Visible = true;
excel.Workbooks.Add();
Without dynamic, you’d need verbose reflection code. With dynamic, you can call members directly - making interop much simpler.
Dynamic and LINQ
You can use dynamic types with LINQ - but with limitations. Since LINQ relies on compile-time type information, dynamic queries may require workarounds:
List<dynamic> items = new()
{
new { Name = "A", Value = 10 },
new { Name = "B", Value = 20 }
};
var result = items.Where(i => i.Value > 15);
foreach (var item in result)
Console.WriteLine(item.Name); // Output: B
This works because the anonymous types are treated as dynamic. But for complex queries, you may need to cast or use reflection.
Performance Considerations
Dynamic types are slower than static types - because the runtime must resolve members using reflection or dynamic dispatch. This adds overhead, especially in tight loops or performance-critical code.
If performance matters, avoid dynamic in hot paths. Use it for flexibility - not speed.
Use dynamic for interop, scripting, and flexible data. Avoid it in core logic, performance-sensitive code, or public APIs. Prefer static typing whenever possible.
Common Mistakes and How to Avoid Them
Dynamic types are easy to misuse. Here are some common mistakes:
- Assuming members exist - always validate before accessing
- Using dynamic in performance-critical code - prefer static types
- Mixing dynamic and static types - leads to confusing errors
- Overusing dynamic - makes code harder to read and maintain
Use dynamic thoughtfully. It’s a powerful tool - but not a substitute for good design.
The dynamic
keyword was introduced in C# 4.0 to support
dynamic languages and interop scenarios - especially with COM and DLR (Dynamic Language Runtime).
Summary
Dynamic types in C# let you defer type checking until runtime - giving you flexibility to work with loosely
typed data, scripting APIs, and external systems. You’ve learned how to declare dynamic variables, use them with
methods, access members, handle runtime errors, and integrate with JSON, COM, and reflection. You’ve also seen
how to use ExpandoObject
for dynamic objects, and how to avoid common mistakes.
By using dynamic types thoughtfully, you can write flexible, adaptable code - while still benefiting from the structure and safety of C#. In the next article, we’ll explore Caller Information - a feature that lets you capture details about the caller of a method, such as file name, line number, and member name.