Type Safety vs. Dynamic Flexibility
C# is historically a strictly typed, compiled language. Strong typing provides compile-time safety and IDE autocomplete features. However, interacting with dynamically typed architectures—such as COM APIs, JSON data, or dynamic languages (IronPython)—requires writing verbose reflection helper code.
The release of C# 4.0 in .NET 4 introduces a hybrid approach: dynamic binding.
The dynamic Keyword
C# 4.0 introduces the dynamic type. Operations on dynamic variables bypass compile-time type validation, resolving their members dynamically at runtime:
// Simple dynamic variable resolution in C# 4.0
dynamic user = GetUserData();
Console.WriteLine(user.FirstName); // Compiled without checks!Behind the scenes, C# utilizes the Dynamic Language Runtime (DLR). If the property FirstName does not exist at runtime, a runtime exception is thrown.
Optional and Named Parameters
C# 4.0 introduces optional parameters with default values, reducing the need for multiple method overloads:
public void CreateLog(string message, string level = "INFO", bool consoleOutput = true) {
// Method body
}We can invoke this method using named arguments:
CreateLog("Service started", consoleOutput: false);Co- and Contravariance
C# 4.0 adds support for covariance and contravariance in generic interfaces and delegates:
- ◆Covariance (out): Allows a method to return a more derived type than specified (e.g. assigning
IEnumerable<String>toIEnumerable<Object>). - ◆Contravariance (in): Allows a method to receive a less derived type than specified.
These language features improve developer productivity and make the .NET framework more expressive.