Dynamic programming in C# is a powerful feature that allows developers to write flexible and dynamic code. It enables the use of dynamic types, which can be particularly useful when dealing with scenarios where the type of data is not known at compile time. This section will cover the basics of dynamic programming, including the dynamic keyword, and provide practical examples and exercises to help you understand and apply these concepts.
Key Concepts
- Dynamic Type: The
dynamickeyword allows you to bypass compile-time type checking. The type of adynamicvariable is resolved at runtime. - ExpandoObject: A class that allows you to dynamically add and remove members at runtime.
- DynamicObject: A base class that provides a way to implement dynamic behavior in your objects.
Dynamic Type
Explanation
The dynamic keyword in C# is used to declare variables whose type is determined at runtime. This can be useful in scenarios where you need to interact with COM objects, work with dynamic languages, or handle JSON data.
Example
using System;
class Program
{
static void Main()
{
dynamic value = 10;
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
value = "Hello, World!";
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
value = DateTime.Now;
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
}
}Explanation
- Initially,
valueis assigned an integer. - Then,
valueis reassigned a string. - Finally,
valueis reassigned aDateTimeobject. - The type of
valueis determined at runtime, and theGetType()method is used to display the type.
ExpandoObject
Explanation
The ExpandoObject class allows you to dynamically add and remove members at runtime. It is part of the System.Dynamic namespace.
Example
using System;
using System.Dynamic;
class Program
{
static void Main()
{
dynamic expando = new ExpandoObject();
expando.Name = "John Doe";
expando.Age = 30;
Console.WriteLine($"Name: {expando.Name}, Age: {expando.Age}");
expando.Greet = new Action(() => Console.WriteLine($"Hello, {expando.Name}!"));
expando.Greet();
}
}Explanation
- An
ExpandoObjectis created and assigned to thedynamicvariableexpando. - Members
NameandAgeare dynamically added. - A method
Greetis dynamically added and invoked.
DynamicObject
Explanation
The DynamicObject class provides a base class for objects that participate in dynamic behavior. By inheriting from DynamicObject, you can override methods to define custom dynamic behavior.
Example
using System;
using System.Dynamic;
class MyDynamicObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = $"You tried to access '{binder.Name}'";
return true;
}
}
class Program
{
static void Main()
{
dynamic obj = new MyDynamicObject();
Console.WriteLine(obj.SomeProperty);
}
}Explanation
MyDynamicObjectinherits fromDynamicObject.- The
TryGetMembermethod is overridden to provide custom behavior when accessing members. - When
SomePropertyis accessed, the custom message is returned.
Practical Exercises
Exercise 1: Dynamic Type
Task: Create a dynamic variable and assign different types of values to it. Print the value and its type after each assignment.
Solution:
using System;
class Program
{
static void Main()
{
dynamic value = 42;
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
value = 3.14;
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
value = "Dynamic Programming";
Console.WriteLine($"Value: {value}, Type: {value.GetType()}");
}
}Exercise 2: ExpandoObject
Task: Create an ExpandoObject and dynamically add properties and methods to it. Print the properties and invoke the methods.
Solution:
using System;
using System.Dynamic;
class Program
{
static void Main()
{
dynamic expando = new ExpandoObject();
expando.FirstName = "Jane";
expando.LastName = "Doe";
expando.GetFullName = new Func<string>(() => $"{expando.FirstName} {expando.LastName}");
Console.WriteLine($"Full Name: {expando.GetFullName()}");
}
}Exercise 3: DynamicObject
Task: Create a class that inherits from DynamicObject and override the TrySetMember method to store dynamic properties in a dictionary. Override the TryGetMember method to retrieve the properties.
Solution:
using System;
using System.Collections.Generic;
using System.Dynamic;
class MyDynamicObject : DynamicObject
{
private Dictionary<string, object> _properties = new Dictionary<string, object>();
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_properties[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return _properties.TryGetValue(binder.Name, out result);
}
}
class Program
{
static void Main()
{
dynamic obj = new MyDynamicObject();
obj.Name = "Dynamic Object";
obj.Value = 12345;
Console.WriteLine($"Name: {obj.Name}, Value: {obj.Value}");
}
}Common Mistakes and Tips
- Type Safety: Using
dynamicbypasses compile-time type checking, which can lead to runtime errors. Use it judiciously. - Performance: Dynamic operations are generally slower than static operations due to the overhead of runtime type resolution.
- Debugging: Debugging dynamic code can be more challenging. Ensure you have proper error handling and logging in place.
Conclusion
Dynamic programming in C# provides a flexible way to handle scenarios where types are not known at compile time. By using the dynamic keyword, ExpandoObject, and DynamicObject, you can create dynamic and adaptable code. However, it's important to use these features judiciously to avoid potential runtime errors and performance issues. In the next section, we will explore memory management and garbage collection in C#.
C# Programming Course
Module 1: Introduction to C#
- Introduction to C#
- Setting Up the Development Environment
- Hello World Program
- Basic Syntax and Structure
- Variables and Data Types
Module 2: Control Structures
Module 3: Object-Oriented Programming
- Classes and Objects
- Methods
- Constructors and Destructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
Module 4: Advanced C# Concepts
- Interfaces
- Delegates and Events
- Generics
- Collections
- LINQ (Language Integrated Query)
- Asynchronous Programming
Module 5: Working with Data
Module 6: Advanced Topics
- Reflection
- Attributes
- Dynamic Programming
- Memory Management and Garbage Collection
- Multithreading and Parallel Programming
