The new features in C# 4.0 are:
• Dynamic binding
• Type variance with generic interfaces and delegates
• Optional parameters
• Named arguments
• COM interoperability improvements
Dynamic binding (Chapters 4 and 19) is C# 4.0’s biggest innovation. This feature
was inspired by dynamic languages such as Python, Ruby, JavaScript, and Smalltalk.
Dynamic binding defers binding—the process of resolving types and members—
from compile time to runtime. Although C# remains a predominantly statically
typed language, a variable of type dynamic is resolved in a late-bound manner. For
example:
dynamic d = "hello";
Console.WriteLine (d.ToUpper()); // HELLO
Console.WriteLine (d.Foo()); // Compiles OK but gives runtime error
Calling an object dynamically is useful in scenarios that would otherwise require
complicated reflection code. Dynamic binding is also useful when interoperating
with dynamic languages and COM components.
Optional parameters (Chapter 2) allow functions to specify default parameter values
so that callers can omit arguments. An optional parameter declaration such as:
void Foo (int x = 23) { Console.WriteLine (x); }
can be called as follows:
Foo(); // 23
Named arguments (Chapter 2) allow a function caller to identify an argument by
name rather than position. For example, the preceding method can now be called
as follows:
Foo (x:5);
Type variance (Chapters 3 and 4) allows generic interfaces and generic delegates to
mark their type parameters as covariant or contravariant. This enables code such as
the following to work:
IEnumerable<string> x = ...;
IEnumerable<object> y = x;
COM interoperability (Chapter 25) has been enhanced in C# 4.0 in three ways. First,
arguments can be passed by reference without the ref keyword. This feature is particularly
useful in conjunction with optional parameters. It means that the following
C# 3.0 code to open a Word document: object o1 = "foo.doc";
object o2 = Missing.Value;
object o3 = Missing.Value;
...
word.Open (ref o1, ref o2, ref o3...);
can now be simplified to:
word.Open ("Foo.doc");
Second, assemblies that contain COM interop types can now be linked rather than
referenced. Linked interop types support type equivalence, avoiding the need for
Primary Interop Assemblies and putting an end to versioning and deployment
headaches.
Third, functions that return variant types from linked interop types are mapped to
dynamic rather than object, eliminating the need for casting.