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.