Dynamic Type In C# Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    14 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of Dynamic Type in C#


Dynamic Type in C#: A Comprehensive Overview

C#, a strongly-typed language by nature, primarily relies on static typing, where the type of a variable is known at compile-time. However, starting with C# 4.0, Microsoft introduced a new feature known as dynamic. This feature allows developers to write less restrictive code that can interact with objects or libraries that are not statically typed. Understanding dynamic typing in C# is crucial for scenarios where you need to work with APIs or scripting languages.

Introduction to Dynamic Types

The dynamic keyword in C# represents an unknown or changing type during compilation. Variables declared as dynamic are treated as being of type object at compile-time but are resolved at runtime. This means the type checking and member access operations for dynamic variables occur at runtime rather than compile-time. Consequently, dynamic typing offers flexibility but sacrifices some of the benefits like IntelliSense, compile-time error detection, and optimizations provided by static typing.

Basic Usage:

dynamic d = "hello"; // string type at runtime
Console.WriteLine(d.Length); // accesses Length property at runtime

Here, d is initially assigned a string value, and its Length property is accessed dynamically.

Key Features and Capabilities

  1. Runtime Resolution:

    • Operations involving dynamic variables are resolved at runtime.
    • This makes it possible to invoke methods, access properties, fields, and indexers, assign values, and perform conversions using variables whose type is unknown until runtime.
  2. Interoperability with COM Objects:

    • Dynamic types simplify interactions with legacy COM (Component Object Model) objects.
    • You no longer need to use interop assemblies or manually cast objects.
    dynamic excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
    excelApp.Visible = true;
    dynamic workbook = excelApp.Workbooks.Add();
    
  3. Accessing Objects Returned from DLR Languages:

    • Dynamic typing supports integration with Dynamic Language Runtime (DLR) languages such as Python and Ruby.

    • Example:

      ScriptEngine engine = Python.CreateEngine();
      ScriptScope scope = engine.CreateScope();
      
      // Assume Python script defines a class with method 'greet'
      engine.Execute(@"
      

    class Greeter: def init(self, name): self.name = name def greet(self): return 'Hello, ' + self.name", scope);

    dynamic greeter = scope.GetVariable("Greeter")("World"); Console.WriteLine(greeter.greet()); // Outputs 'Hello, World'

    
    
  4. Handling JSON Data:

    • Libraries like Newtonsoft.Json provide serialization/deserialization to JSON objects.
    • Using dynamic, you can easily work with JSON data without creating corresponding classes.
    var jsonString = "{\"name\":\"John\", \"age\":30}";
    dynamic json = JsonConvert.DeserializeObject(jsonString);
    Console.WriteLine($"Name: {json.name}, Age: {json.age}");
    
  5. Dynamic Method Dispatch:

    • C# provides a way to perform method overloading dynamically based on the argument types.

    • Example:

      public void Print(dynamic input)
      {
          Console.WriteLine(input.GetType());
      }
      
      Print("Hello"); // Outputs System.String
      Print(30);      // Outputs System.Int32
      

Advantages and Disadvantages

Advantages:

  1. Simplification: Reduces the verbosity of interop calls and simplifies working with heterogeneous APIs.
  2. Flexibility: Permits more flexible type definitions, suitable for scenarios with varying object structures.
  3. Improved Performance with DLR: Dynamic operations are optimized by the DLR, providing faster execution compared to using reflection.

Disadvantages:

  1. Loss of Compile-Time Checks: Removes type-checking at compile-time, leading to potential runtime errors if incorrect methods or properties are accessed.
  2. IntelliSense Not Available: Developers lose the benefits of IntelliSense and auto-completion, as the IDE cannot infer the type until runtime.
  3. Debugging Challenges: Debugging can become more complex due to the dynamic resolution of members.

Important Methods and Properties

  • DynamicObject Class:
    • Provides support for dynamic operations in custom classes.

    • Methods like TryGetMember, TrySetMember, TryInvokeMember, etc., control how dynamic operations are handled.

      public class MyCustomDynamic : DynamicObject
      {
          private Dictionary<string, object> dictionary = new Dictionary<string, object>();
      
          public override bool TryGetMember(GetMemberBinder binder, out object result)
          {
              return dictionary.TryGetValue(binder.Name, out result);
          }
      
          public override bool TrySetMember(SetMemberBinder binder, object value)
          {
              dictionary[binder.Name] = value;
              return true;
          }
      }
      

Best Practices

  1. Use Sparingly: Apply dynamic typing judiciously, ideally only in necessary scenarios.
  2. Error Handling: Implement comprehensive error handling to manage possible runtime exceptions.
  3. Documentation: Ensure well-documented code to make it easier to understand which variables are dynamic and their expected behaviors.

Comparison with Other Types

  • Var vs. Dynamic:

    • var allows type inference at compile-time based on the initial assignment.
    • dynamic defers type determination to runtime, enabling more flexibility but sacrificing compile-time checks and optimizations.
  • Object vs. Dynamic:

    • object type requires casting for member access and does not support implicit type conversion.
    • dynamic type eliminates the need for casting and supports various operations implicitly via DLR binding.

Conclusion

The dynamic type in C# is a powerful feature that enhances the language's flexibility by allowing operations to be resolved at runtime. While this feature can be particularly useful when working with COM objects, heterogeneous APIs, or integrating with DLR languages, developers should weigh the trade-offs carefully. Employing dynamic types judiciously, combined with thorough error-handling mechanisms, can help leverage the benefits while minimizing the drawbacks.


Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement Dynamic Type in C#

Table of Contents

  1. Introduction to Dynamic Types
  2. Advantages and Disadvantages of Dynamic Types
  3. Basic Usage of Dynamic Types
  4. Dynamic Types with JSON Data
  5. Dynamic Types with External Libraries (e.g., CSV)
  6. Using Dynamic with COM Objects
  7. Reflection and Dynamic Types
  8. Best Practices and Considerations

1. Introduction to Dynamic Types

In C#, which is primarily a statically-typed language, the dynamic keyword allows variables to be resolved at runtime instead of compile-time. This is particularly useful when you don't know the type of an object at compile time.

Key Points:

  • Runtime Resolution: The type of a dynamic variable is determined at the time of execution.
  • Interoperability: Facilitates ease of use when working with APIs or data formats that aren't strongly-typed.
  • Flexibility: Enables more flexibility in handling diverse and changing data structures.

2. Advantages and Disadvantages of Dynamic Types

Advantages:

  1. Ease of Use:

    • Simplifies working with dynamic data sources where the schema changes frequently.
  2. Interoperability:

    • Enhances compatibility with dynamic languages and COM objects.
  3. Reduced Boilerplate:

    • Reduces the need for explicit casting and type declarations, making code cleaner.

Disadvantages:

  1. Performance Overhead:

    • Operations on dynamic variables are slower due to runtime type resolution.
  2. Lack of Compile-Time Checking:

    • Errors are only caught at runtime, leading to potential crashes if not handled properly.
  3. Readability and Maintainability:

    • Code using dynamic can be harder to understand and maintain, as the types are not explicitly defined.

3. Basic Usage of Dynamic Types

Let's start with some simple examples to understand how to use dynamic types in C#.

Example 1: Basic Dynamic Usage

using System;

class Program
{
    static void Main()
    {
        dynamic dynamicVariable = 42;
        
        // Using the dynamic variable as an integer
        Console.WriteLine($"Number: {dynamicVariable}");
        
        // Reassigning to a different type
        dynamicVariable = "Hello, Dynamic!";
        
        // Using the dynamic variable as a string
        Console.WriteLine($"Message: {dynamicVariable.ToUpper()}");
        
        // Adding two dynamics (runtime type determination)
        dynamic a = 10;
        dynamic b = 20;
        dynamic sum = a + b;
        Console.WriteLine($"Sum: {sum}");
    }
}

Output:

Number: 42
Message: HELLO, DYNAMIC!
Sum: 30

Explanation:

  • dynamicVariable is initially an int and then reassigned to a string.
  • Methods and properties are resolved at runtime based on the current type of the variable (e.g., ToUpper() on a string).
  • Arithmetic operations between dynamic variables are performed based on their runtime types.

Example 2: Dynamic with Anonymous Types

using System;

class Program
{
    static void Main()
    {
        dynamic person = new 
        {
            Name = "Alice",
            Age = 30,
            IsEmployed = true
        };
        
        // Accessing properties
        Console.WriteLine($"Name: {person.Name}, Age: {person.Age}, Employed: {person.IsEmployed}");
        
        // Adding a new property dynamically (not recommended as it breaks type safety)
        // person.Email = "alice@example.com"; // This will work but should be handled carefully
        
        // Attempting to access a non-existent property will throw a RuntimeBinderException
        try
        {
            Console.WriteLine($"Email: {person.Email}");
        }
        catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Output:

Name: Alice, Age: 30, Employed: True
Error: 'AnonymousType#1' does not contain a definition for 'Email'

Explanation:

  • Anonymous types are often used with dynamic to create flexible data structures.
  • Accessing properties of a dynamic variable with anonymous types is possible but should be done cautiously to avoid runtime errors.
  • Attempting to access non-existent properties results in a RuntimeBinderException.

4. Dynamic Types with JSON Data

Dynamic types are particularly useful when working with JSON data, where the structure might change or is unknown at compile time.

Example 3: Parsing JSON with Dynamic Types

First, ensure you have the Newtonsoft.Json package installed. You can add it via NuGet Package Manager:

  • NuGet Package: Newtonsoft.Json
using System;
using Newtonsoft.Json;
using System.IO;

class Program
{
    static void Main()
    {
        string jsonContent = @"
        {
            ""name"": ""Bob"",
            ""age"": 25,
            ""isStudent"": true,
            ""courses"": [""Math"", ""Science""]
        }";

        // Deserialize JSON to dynamic
        dynamic person = JsonConvert.DeserializeObject(jsonContent);
        
        // Accessing properties
        Console.WriteLine($"Name: {person.name}");
        Console.WriteLine($"Age: {person.age}");
        Console.WriteLine($"Is Student: {person.isStudent}");
        
        // Accessing array elements
        Console.Write("Courses: ");
        foreach (var course in person.courses)
        {
            Console.Write($"{course} ");
        }
        Console.WriteLine();
        
        // Modifying properties dynamically
        person.age = 26;
        Console.WriteLine($"Updated Age: {person.age}");
    }
}

Output:

Name: Bob
Age: 25
Is Student: True
Courses: Math Science 
Updated Age: 26

Explanation:

  • The JSON content is deserialized into a dynamic variable using JsonConvert.DeserializeObject.
  • Properties and array elements can be accessed using dot notation (person.name, person.courses).
  • Properties can be modified dynamically.

Example 4: Reading JSON from a File with Dynamic

using System;
using Newtonsoft.Json;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "person.json";
        
        // Sample JSON content in person.json
        /*
        {
            "name": "Charlie",
            "age": 28,
            "profile": {
                "city": "New York",
                "occupation": "Developer"
            }
        }
        */
        
        if (!File.Exists(filePath))
        {
            Console.WriteLine($"File {filePath} does not exist.");
            return;
        }
        
        string fileContent = File.ReadAllText(filePath);
        
        // Deserialize JSON to dynamic
        dynamic person = JsonConvert.DeserializeObject(fileContent);
        
        // Accessing nested properties
        Console.WriteLine($"Name: {person.name}");
        Console.WriteLine($"Age: {person.age}");
        Console.WriteLine($"City: {person.profile.city}");
        Console.WriteLine($"Occupation: {person.profile.occupation}");
    }
}

Output (assuming person.json exists and contains the sample JSON above):

Name: Charlie
Age: 28
City: New York
Occupation: Developer

Explanation:

  • The JSON content is read from a file and deserialized into a dynamic object.
  • Nested properties can be accessed using dot notation (person.profile.city).

5. Dynamic Types with External Libraries (e.g., CSV)

While dynamic types are not commonly used for CSV parsing, you can still leverage them to handle dynamic data structures.

Example 5: Parsing CSV with Dynamic Types

For this example, we'll use the CsvHelper library to parse a CSV file. First, install the package:

  • NuGet Package: CsvHelper
using System;
using System.Globalization;
using System.IO;
using CsvHelper;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        string filePath = "data.csv";
        
        // Sample CSV content in data.csv
        /*
        Name,Age,Email
        Alice,30,alice@example.com
        Bob,25,bob@example.com
        */
        
        if (!File.Exists(filePath))
        {
            Console.WriteLine($"File {filePath} does not exist.");
            return;
        }
        
        using (var reader = new StreamReader(filePath))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            // Parse the CSV to dynamic
            var records = csv.GetRecords<dynamic>();
            
            foreach (var record in records)
            {
                Console.WriteLine($"Name: {record.Name}, Age: {record.Age}, Email: {record.Email}");
            }
        }
    }
}

Output (assuming data.csv contains the sample CSV above):

Name: Alice, Age: 30, Email: alice@example.com
Name: Bob, Age: 25, Email: bob@example.com

Explanation:

  • The CSV file is read and parsed into a collection of dynamic objects using CsvHelper.
  • Each record's properties can be accessed using dot notation (record.Name, record.Age).

6. Using Dynamic with COM Objects

Dynamic types can greatly simplify working with COM (Component Object Model) objects, which are common in legacy applications and automation.

Example 6: Working with Excel Using Dynamic Types

To demonstrate this, you need to add a reference to the Microsoft Excel library. The easiest way is to use the Microsoft.Office.Interop.Excel package from NuGet:

  • NuGet Package: Microsoft.Office.Interop.Excel

Note: Ensure Microsoft Excel is installed on your machine to run this example.

using System;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        // Create a new Excel application instance
        dynamic excelApp = new Application();
        excelApp.Visible = true;
        
        // Create a new workbook and worksheet
        dynamic workbook = excelApp.Workbooks.Add();
        dynamic worksheet = workbook.Worksheets[1];
        
        // Write data to the worksheet
        worksheet.Cells[1, 1] = "Name";
        worksheet.Cells[1, 2] = "Age";
        worksheet.Cells[2, 1] = "Alice";
        worksheet.Cells[2, 2] = 30;
        worksheet.Cells[3, 1] = "Bob";
        worksheet.Cells[3, 2] = 25;
        
        // Add a chart to the worksheet
        dynamic chartObjects = worksheet.ChartObjects();
        dynamic chartObject = chartObjects.Add(50, 200, 300, 200);
        dynamic chart = chartObject.Chart;
        chart.ChartType = XlChartType.xlColumnClustered;
        chart.SetSourceData(worksheet.Range["A1:B3"]);
        
        // Clean up
        // excelApp.Quit();
        // System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
    }
}

Output:

  • An Excel application opens with a new workbook containing a worksheet with data and a chart.

Explanation:

  • A new Excel application instance is created using dynamic.
  • A workbook and worksheet are created and populated with data.
  • A chart is added to visualize the data.
  • Note: To avoid memory leaks, ensure you release COM objects properly. However, this has been commented out for brevity.

7. Reflection and Dynamic Types

Dynamic types can be combined with reflection to perform more complex operations at runtime.

Example 7: Using Reflection with Dynamic Types

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // Create an instance of a sample class dynamically
        dynamic sampleInstance = Activator.CreateInstance(typeof(SampleClass));
        
        // Set properties using reflection
        PropertyInfo nameProperty = sampleInstance.GetType().GetProperty("Name");
        nameProperty.SetValue(sampleInstance, "Dynamic Reflection");
        
        PropertyInfo ageProperty = sampleInstance.GetType().GetProperty("Age");
        ageProperty.SetValue(sampleInstance, 100);
        
        // Get properties using reflection
        Console.WriteLine($"Name: {nameProperty.GetValue(sampleInstance)}");
        Console.WriteLine($"Age: {ageProperty.GetValue(sampleInstance)}");
        
        // Invoke a method dynamically
        dynamic result = sampleInstance.Greet();
        Console.WriteLine(result);
    }
}

class SampleClass
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public string Greet()
    {
        return $"Hello, {Name}! You are {Age} years old.";
    }
}

Output:

Name: Dynamic Reflection
Age: 100
Hello, Dynamic Reflection! You are 100 years old.

Explanation:

  • An instance of SampleClass is created dynamically using Activator.CreateInstance.
  • Properties are set and retrieved using reflection (PropertyInfo).
  • A method (Greet) is invoked dynamically.

8. Best Practices and Considerations

While dynamic types offer great flexibility, they also come with trade-offs. Here are some best practices to consider:

A. Use Dynamically When Necessary

  • Avoid Overusing Dynamic: Stick to strongly-typed variables whenever possible to leverage compile-time checks and optimizations.
  • Target Scenarios: Reserve dynamic types for scenarios where the type is truly unknown at compile time, such as JSON parsing, COM automation, or interacting with dynamic APIs.

B. Handle Runtime Errors Gracefully

  • Exception Handling: Always use try-catch blocks to handle potential RuntimeBinderException errors.

    try
    {
        dynamic dynamicObject = new { Name = "Example" };
        Console.WriteLine(dynamicObject.NonExistentProperty);
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
    

    Output:

    Error: 'AnonymousType#1' does not contain a definition for 'NonExistentProperty'
    

C. Reassign Dynamic Variables Carefully

  • Type Changes: Be cautious when reassigning dynamic variables to new types, as methods and properties may not match across different types.

    dynamic dynamicVar = 42;
    Console.WriteLine(dynamicVar.ToString()); // Ok: int has ToString()
    
    dynamicVar = "Hello";
    Console.WriteLine(dynamicVar.ToString()); // Ok: string has ToString(), different implementation
    Console.WriteLine(dynamicVar.Length);   // Ok: string has Length property
    // dynamicVar.CallMethodOnString();   // This will throw a RuntimeBinderException if not a method on string
    

D. Document Dynamic Code Extensively

  • Readability: Code using dynamic types can be harder to read and maintain. Include detailed comments and documentation to explain the purpose and usage of dynamic variables.

    // Deserializing JSON to dynamic for flexibility
    dynamic jsonResult = JsonConvert.DeserializeObject(jsonContent);
    // Accessing nested property dynamically
    string cityName = jsonResult.location.city;
    

E. Consider Memory and Performance Implications

  • Performance Overhead: Operations on dynamic types are slower due to runtime type resolution. Benchmark performance-critical sections to identify bottlenecks.
  • Memory Usage: Ensure proper management of resources, especially when working with COM objects or large dynamic data structures.

F. Leverage Strongly-Typed Alternatives When Possible

  • Static Typing: Prefer strongly-typed variables and classes to ensure compile-time safety and type checking.

  • Interfaces and Generics: Use interfaces and generics to achieve flexibility while maintaining type safety.

    // Strongly-typed class
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    Person person = new Person { Name = "Alice", Age = 30 };
    

Conclusion

Dynamic types in C# provide a powerful mechanism to handle loose-typed data and interact with dynamic environments. By understanding when and how to use dynamic types, you can write more flexible and adaptable code. However, always weigh the benefits against the potential downsides of runtime errors and performance overhead.

Feel free to explore the examples provided and adapt them to your own projects to deepen your understanding of dynamic typing in C#.


References:


Additional Resources:


Top 10 Interview Questions & Answers on Dynamic Type in C#

1. What is the 'dynamic' type in C#?

Answer: The dynamic type in C# is a static type that bypasses compile-time type checking. This means the object's type is determined at runtime, allowing for more flexible scenarios such as interacting with dynamic languages or COM objects. However, this flexibility comes with the trade-off of losing the benefits of compile-time error checking.

2. How does the 'dynamic' type differ from the 'object' type in C#?

Answer: Both dynamic and object types can hold any data but there are key differences:

  • Compile-Time vs. Runtime: With object, all types are cast to object during compilation, and only operations supported by object are allowed, such as calling ToString(). Compile-time binding occurs.
  • Dynamic Binding: The dynamic type defers all decisions about member access, method calls, properties, etc., until runtime. Operations with dynamic can be resolved based on actual data type at runtime.
  • Performance: Using object involves boxing and unboxing with minor performance overhead, whereas using dynamic has a significant runtime cost due to reflection.

3. When should you use the 'dynamic' keyword in C#?

Answer: Use dynamic when:

  • Interacting with dynamic objects that do not have a well-known static type (e.g., IronPython scripts).
  • Working with COM objects, where method signatures might not be known at compile time.
  • Creating a more flexible and less verbose API for consumers where method calls and property accesses need to be flexible.
  • Writing code that requires frequent changes and where refactoring costs can be minimized.

4. Can you provide an example of using the 'dynamic' type in C#?

Answer:

using System;
class Program {
    static void Main(string[] args) {
        dynamic d = new System.Dynamic.ExpandoObject();
        d.Name = "Alice";
        d.Age = 25;
        Console.WriteLine($"Name: {d.Name}, Age: {d.Age}");

        dynamic calculator = new Calculator();
        int sum = calculator.Add(10, 5);
        Console.WriteLine($"Sum: {sum}");
    }
}

In this example:

  • An ExpandoObject is created and its properties are set dynamically.
  • The Calculator class’s Add method is called using a dynamic reference.

5. Is it possible to declare a field, property, or event as 'dynamic'?

Answer: No, fields, properties, and events must have a compile-time known type and cannot be dynamic. The dynamic keyword can only be applied to local variables within a method.

6. Does the 'dynamic' keyword support extension methods in C#?

Answer: Yes, extension methods work with dynamic types. At runtime, the extension method will be available if the correct parameters match the type of the dynamic object. For example:

public static class Extensions {
    public static string ReverseText(this dynamic source) {
        char[] charArray = source.ToCharArray();
        Array.Reverse(charArray);
        return new string(charArray);
    }
}

// Usage
dynamic text = "Hello";
Console.WriteLine(text.ReverseText());  // Outputs: "olleH"

7. What are the benefits of using 'dynamic' type in C#?

Answer: Benefits include:

  • Flexibility: Interacting with dynamic languages and APIs without type mismatch errors.
  • Ease of Use: Simplifies code when working with non-static types, reducing boilerplate casting.
  • Performance Optimization: For certain APIs like COM interops, using dynamic can reduce the verbosity of explicit conversions.
  • Rapid Prototyping: Allows faster development without worrying about type mismatches at compile time.

8. What are the drawbacks of using the 'dynamic' type in C#?

Answer: Drawbacks include:

  • Lack of IntelliSense Support: IDEs cannot predict members or methods, making it harder for developers to understand and use the object’s capabilities.
  • Loss of Compile-Time Safety: Errors related to missing members or incorrect method calls are caught only at runtime, leading to potential application crashes.
  • Performance Overhead: Method invocations and property accesses involve reflection, which is slower than statically typed bindings.

9. Can you catch exceptions from a 'dynamic' object at compile-time?

Answer: No, exceptions from a dynamic object are caught at runtime because all member access and method calls are resolved during execution. This eliminates the ability of the compiler to identify errors beforehand.

10. How do I convert a 'dynamic' type back to a static type in C#?

Answer: You can explicitly cast a dynamic variable to a static type. The compiler assumes the specified type and checks whether the member accesses are valid on that static type.

You May Like This Related .NET Topic

Login to post a comment.