Chapter 17. Dynamic Types

Throughout this book, I have emphasized the importance of type and type safety. After all, C# is a strongly typed language, and you are most effective when you use the C# type system along with the compiler to eliminate any programming errors early at compile time rather than later at run time. However, there are some areas where the static, strongly-typed nature of C# creates headaches. Those areas often involve interoperability. In this chapter, I will introduce you to the dynamic type (which is new in C# 4.0) and discuss what it means from both a language standpoint as well as a runtime standpoint.

What does dynamic Mean?

In a nutshell, dynamic is a static type that you can use where you would use any other static type. However, it is special because it allows you to tell the compiler you are not quite sure exactly what type it references and that it should defer any irresolvable type decisions to run time. You can assign any reference or value type to an instance of dynamic. Under the hood, the compiler coupled with the Dynamic Language Runtime (DLR)[77] produces the magic to get this done by deferring the work of the compiler to run time.

Note

Make sure you keep a clear distinction in your mind between dynamic types and implicitly typed local variables (declared with the var keyword). Implicitly typed local variables are strongly typed, even though you don't have to type the full type name that they reference. Instances of dynamic are truly dynamic and are generally resolved at run time. I mention this here to avoid any potential confusion.

When programming in C#, you are usually programming against static .NET types that might have been coded in C#, C++/CLI, and so on. But what about when you have to interoperate with types created by dynamic languages such as IronPython or IronRuby? Or what about when you have to interoperate with COM objects that implement IDispatch to support automation via late-bound interfaces?

Let's consider COM/IDispatch interoperability for a moment. Additionally, assume that I am talking about purely late-bound IDispatch implementations rather than dual interface implementations. In C# 3.0, you had to rely on gratuitous amounts of reflection to dynamically invoke the methods and properties of an instance that just feels cumbersome and unnatural. What happens behind the scenes is that the Runtime Callable Wrapper (RCW), which acts as the proxy between the .NET runtime and the COM object, translates reflection operations into IDispatch operations. This allows you to reflect over a COM object that implements the IDispatch automation interface.

If you used VB.NET rather than C# 3.0, the experience would have been much more pleasant because VB.NET shields you from all the reflection work. Now that C# 4.0 offers dynamic type support in concert with the DLR, its functionality is at par with VB.NET with respect to working with dynamically typed objects.

To better illustrate what I am talking about, let's consider a short example. Suppose that you want to create a new Excel document with some text in the first cell. Additionally, force yourself to use only the late bound IDispatch interfaces for the sake of the example. If you are familiar with coding against Office apps such as Excel, forget for a moment the existence of Primary Interop Assemblies (PIA). The example code in C# 3.0 might look like the following:

using System;
using System.Reflection;

static class EntryPoint
{
    static void Main() {
        // Create an instance of Excel
        Type xlAppType = Type.GetTypeFromProgID( "Excel.Application" );
        object xl = Activator.CreateInstance( xlAppType );

        // Set Excel to be visible
        xl.GetType().InvokeMember( "Visible",
                                   BindingFlags.SetProperty,
                                   null,
                                   xl,
                                   new object[] { true } );

        // Create a new workbook
        object workbooks = xl.GetType().InvokeMember( "Workbooks",
                                                      BindingFlags.GetProperty,
                                                      null,
                                                      xl,
                                                      null );

        workbooks.GetType().InvokeMember( "Add",
                                          BindingFlags.InvokeMethod,
                                          null,
                                          workbooks,
                                          new object[] { −4167 } );

        // Set the value of the first cell
        object cell = xl.GetType().InvokeMember( "Cells",
                                                 BindingFlags.GetProperty,
                                                 null,
xl,
                                                 new object[] { 1, 1 } );
        cell.GetType().InvokeMember( "Value2",
                                     BindingFlags.SetProperty,
                                     null,
                                     cell,
                                     new object[] { "C# Rocks!" } );

        Console.WriteLine( "Press Enter to Continue..." );
        Console.ReadLine();
    }
}

This coding style is both ugly and cumbersome. From glancing at the code, it's difficult to tell which methods and properties of the Excel objects you are actually calling. In this code, after creating a new instance of the application, you make it visible, access the Workbooks property to create a new workbook, and then put some data in the first cell. Now, let's take a look at the new and improved way of doing this using dynamic in C# 4.0:

using System;

static class EntryPoint
{
    static void Main() {
        // Create an instance of Excel
        Type xlAppType = Type.GetTypeFromProgID( "Excel.Application" );
        dynamic xl = Activator.CreateInstance( xlAppType );

        // Set Excel to be visible
        xl.Visible = true;

        // Create a new workbook
        dynamic workbooks = xl.Workbooks;
        workbooks.Add( −4167 );

        // Set the value of the first cell
        xl.Cells[1, 1].Value2 = "C# Rocks!";

        Console.WriteLine( "Press Enter to Continue..." );
        Console.ReadLine();
    }
}

The spirit of this code is much easier to follow. You can clearly see which properties you are accessing and which methods you are calling. dynamic brings a lot to the table and facilitates more readable code in these interoperability situations.

How Does dynamic Work?

How is this magic happening? Although dynamic is a real static type in the C# language, the compiler translates instances of dynamic into instances of object with an attribute attached to it at the CLR level. To illustrate this, consider the following code that will not compile:

class C
{
    // This will not compile!!!
    void Foo( object o ) { }
    void Foo( dynamic d ) { }
}

If you attempt to compile this code, you will get the following compiler error:

error CS0111: Type 'C' already defines a member called 'Foo' with the same parameter types

Thus, for the sake of overload resolution, dynamic and object are equal. To see the attribute in action, try compiling the following code into a library assembly:

class C
{
    void Foo( dynamic d ) { }
}

I find it easiest to just compile this on the command line using the following where <filename> is replaced with the C# code file name:

csc /target:library <filename>

Once you get this compiled, load the compiled assembly into Reflector and examine the code Reflector shows for the class. At the time of this writing, Reflector knows nothing about dynamic; the code Reflector shows can be seen here:

internal class C
{
    // Methods
    public C();
    private void Foo([Dynamic] object d);
}

You can see that the compiler attached the DynamicAttribute attribute to the parameter d to denote that it is actually dynamic.

I mentioned in a previous section that the compiler defers completion of its work until run time when it encounters dynamic types. In essence, dynamic types and dynamic expressions are opaque to the compiler; it cannot see through them. Therefore, the compiler collects all its known information and emits what's called a dynamic call site. At run time, when all type information is available, the C# runtime binder and the DLR complete the work of resolving dynamic types and performing the necessary operations.

Naturally, this means that the compiler's type system is bypassed to a certain degree at compile time. In fact, the C# runtime binder contains a subset of the compiler's functionality. When the C# runtime binder needs to throw an exception, the error message in the exception is the same one as in the compiler. This uniformity really helps when it comes to diagnosing problems at run time because you are presented with the same errors that you're familiar with. To illustrate this point, consider the following code that will not compile:

class C
{
    public void Foo() {}
}

static class EntryPoint
{
    static void Main() {
        C obj = new C();
        obj.Bar();
    }
}

As you would expect, you end up with a compiler error. The output looks like the following:

error CS1061: 'C' does not contain a definition for 'Bar' and no extension method 'Bar'
accepting a first argument of type 'C' could be found (are you missing a using directive or
an assembly reference?)

Now consider the following example, in which it actually does compile because you are using dynamic to hold the instance of C:

class C
{
    public void Foo() {}
}

static class EntryPoint
{
    static void Main() {
        dynamic dynobj = new C();
        dynobj.Bar();
    }
}

In this case, the error that you expect to see is deferred until run time, and if you execute this example, you will see the following results on the console:

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'C' does not
contain a definition for 'Bar'
at CallSite.Target(Closure , CallSite , Object )

at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
at EntryPoint.Main()

Note

Yes, there is a slight discrepancy between the exception message and the compiler error message. That is because dynamic does not currently support extension methods.

The Great Unification

Something that dynamic does really well is unify the various ways to call into types implemented by various dynamic languages and technologies. When you're coding in C# 4.0, you don't have to be concerned about the origin of the dynamic object. For example, it could be one of the following:

  • An object from a DLR-based language such as IronPython or IronRuby

  • A late-bound COM object that only implements the IDispatch interface

  • An object that implements IDynamicMetaObjectProvider (which I will explain later in the section "Objects with Custom Dynamic Behavior")

  • A plain old .NET statically typed object

For plain old .NET objects, the call site uses reflection to bind to the proper member. If the object is a COM object, it reflects over the RCW that acts as a .NET proxy object to the COM object. The RCW translates the reflection operations into the matching IDispatch operations in order to do the binding. If the dynamic object instance implements the IDynamicMetaObjectProvider interface, the DLR will use it when performing the binding. IDynamicMetaObjectProvider is a powerful extension mechanism for creating custom dynamic behavior.

Call Sites

So far, the dynamic examples that I have shown only demonstrate accessing a member of a dynamic instance; that is, using a dynamic receiver. The opposite of a dynamic receiver is a static receiver, which is what you use to access a member through a statically typed variable. Implementation-wise, that is probably the easiest of all dynamic operations for the compiler because it knows practically nothing (because the dynamic receiver is opaque to it). Thus the compiler wraps up all the information it has available and emits it in what is called a call site. The call site has a target delegate that is invoked to handle the dynamic call. Thus, the call site is the portal into the DLR.

Note

If you are interested in investigating the internals of call sites, I welcome you to use ILDASM to spelunk around through a compiled assembly that uses dynamic. If you are not an IL juggernaut, try opening the compiled assembly using Reflector to see the call sites in C#. This will also give you an idea of the complexity of the work the compiler is doing for you.

Why did I say that accessing members on dynamic instances was the easy for the compiler? Consider the following example:

using System;

class C
{
    void ProcessInput( int x ) {
        Console.WriteLine( "int: " + x.ToString() );
    }

    public void ProcessInput( string msg ) {
        Console.WriteLine( "string: " + msg );
    }

    public void ProcessInput( double d ) {
        Console.WriteLine( "double: " + d.ToString() );
    }
}

static class EntryPoint
{
    static void Main() {
        dynamic obj1 = 123;
        dynamic obj2 = "C# Rocks!";
        dynamic obj3 = 3.1415;

        C c = new C();
        c.ProcessInput( obj1 );         // #1
        c.ProcessInput( obj2 );         // #2

        dynamic cObj = c;
        cObj.ProcessInput( obj3 );      // #3
    }
}

What output would you expect from the code above? In the case of calls #1 and #2, the compiler knows that you are calling members on the statically typed variable C; that is, through a static receiver. Therefore, it can go ahead and verify that there are some public members of this name, which there are. Had there been none, it would have complained with a compiler error. However, the compiler has no idea how to complete overload resolution as it does not have enough information to do so because the parameters are opaque dynamic types. Therefore, it must defer the overload resolution to run time. For call #3, the compiler knows even less than for #1 and #2 because you are calling via a dynamic receiver. If you execute the preceding example, you will get the following results:

double: 123
string: C# Rocks!
double: 3.1415

Pay attention to which overloads were called. Notice that #1 called the overload that accepts a double. That's because the overload that accepts int is not public, and the int parameter is implicitly convertible to double. The call site was instrumental in selecting the overload at run time based upon the information that it knew from the compiler.

Now, consider one small but significant change to the example code:

class C
{
    public void ProcessInput( int x ) {
        Console.WriteLine( "int: " + x.ToString() );
    }

    public void ProcessInput( string msg ) {
        Console.WriteLine( "string: " + msg );
    }

    void ProcessInput( double d ) {
        Console.WriteLine( "double: " + d.ToString() );
    }
}

Notice that I have now made the overload that accepts int public but the overload that accepts double private. Which overloads do you think will be selected at run time now? If you execute the modified example, you will get the following results:

int: 123
string: C# Rocks!

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
 'C.ProcessInput(double)' is inaccessible due to its pr

otection level

   at CallSite.Target(Closure , CallSite , Object , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1
arg1)
at EntryPoint.Main() in dynamic_parms_2.cs:line 30

Notice that it failed to find a proper overload for call #3. That is because there is no public overload that accepts a double, and double is not implicitly convertible to any of the types in the available overloads.

Objects with Custom Dynamic Behavior

Objects that implement IDynamicMetaObjectProvider can be the target of dynamic instances. You have a highly extensible mechanism for creating custom dynamic behavior in which you define what it means to access members of a dynamic type. In reality, however, you will probably only rarely directly implement IDynamicMetaObjectProvider. Instead, you should derive your custom dynamic type from the System.Dynamic.DynamicObject. DynamicObject that provides plenty of virtual methods you can override to create your custom dynamic behavior.

Note

IDynamicMetaObjectProvider and DynamicMetaObject are significant types at the heart of creating custom dynamic behavior. But because deriving from DynamicObject is the recommended way of creating custom dynamic objects, I will not go into the details of these two types. I recommend that you consult the MSDN documentation to find out more about them and the important role they play in dynamic objects.

The DynamicObject class, whose abbreviated class definition is shown here, has a variety of virtual methods you can override:

public class DynamicObject : IDynamicMetaObjectProvider
{
    ...

    public virtual IEnumerable<string> GetDynamicMemberNames();
    public virtual DynamicMetaObject GetMetaObject(Expression parameter);
    public virtual bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out
object result);
    public virtual bool TryConvert(ConvertBinder binder, out object result);
    public virtual bool TryCreateInstance(CreateInstanceBinder binder, object[] args,
outobject result);
    public virtual bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
    public virtual bool TryDeleteMember(DeleteMemberBinder binder);
    public virtual bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object
result);
    public virtual bool TryGetMember(GetMemberBinder binder, out object result);
    public virtual bool TryInvoke(InvokeBinder binder, object[] args, out object result);
public virtual bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object);
result);
    public virtual bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value);
    public virtual bool TrySetMember(SetMemberBinder binder, object value);
    public virtual bool TryUnaryOperation(UnaryOperationBinder binder, out object result);

    ...
}

The names of the methods start with the word Try because the call site, by calling these methods, is asking the dynamic type whether it can perform the operation. If it can, the method performs the work and then returns true. Otherwise, if the method returns false, the call site will determine the behavior, which often results in it throwing an exception if these methods return false. All the default implementations of the previous methods return false.

Here's a very cursory example showing a type deriving from DynamicObject:

using System;
using System.Dynamic;
using System.Collections.Generic;

class MyDynamicType : DynamicObject
{
    public override bool TryInvokeMember( InvokeMemberBinder binder,
                                          object[] args,
                                          out object result ) {
        result = null;
        Console.WriteLine( "Dynamic invoke of " + GetType() +
                           "." + binder.Name + "()" );
        return true;
    }

    public override bool TrySetMember( SetMemberBinder binder,
                                       object Value ) {
        Console.WriteLine( "Dynamic set of property " + GetType() +
                           "." + binder.Name + " to " +
                           Value );

        return true;
    }

    public void DoDefaultWork() {
        Console.WriteLine( "Performing default work" );
    }
}

static class EntryPoint
{
    static void Main() {
        dynamic d = new MyDynamicType();

        d.DoDefaultWork();
        d.DoWork();
        d.Value = 42;
d.Count = 123;
    }
}

In the Main method, after assigning a dynamic variable with a new instance of MyDynamicType, you can then perform some operations on it. Notice that the first method called is DoDefaultWork, and MyDynamicType actually has a method named DoDefaultWork. In this case, the call site reflects over the type and notices it, thus calling it directly. For the call to DoWork, because MyDynamicType does not implement DoWork yet it does implement IDynamicMetaObjectProvider by deriving from DynamicObject, the call site invokes TryInvokeMember to perform the operation. Similarly, the assignment to the Value and Count properties results in a call to TrySetMember. Thus, the output from executing the above code is the following:

Performing default work
Dynamic invoke of MyDynamicType.DoWork()

Dynamic set of property MyDynamicType.Value to 42
Dynamic set of property MyDynamicType.Count to 123

As you can see, DynamicObject provides quite a bit of power to control what happens during operations on dynamic instances. For example, you might have the need to create some sort of proxy object that sits between the calling code and the implementation. Imagine you have an application that communicates with some sort of legacy component through P/Invoke in a very complicated way that might require multiple P/Invoke operations for one logical operation. By deriving from DynamicObject, you could create a custom dynamic type that allows those complicated operations to be performed in one dynamic method call from the perspective of the consumer.

Imagine an application that is extensible via scripting. Suppose that there is some directory in the file system in which various scripts reside. By creating a custom dynamic type, you can expose each one of those scripts as separate method calls. Users who are script-savvy can then easily modify the application by modifying the scripts. You can even code the custom dynamic type so it exposes new dynamic methods by enumerating the script in the directory so that users could add new methods to the dynamic type simply by placing new scripts in the directory.

As yet another example, consider the fact that static classes in C# allow only single inheritance, thus allowing only one class to reuse the implementation of one other class. Using custom dynamic types, you could build dynamic types that emulate the behavior of COM aggregation, whereby multiple types are aggregated into one. In C++, which supports multiple inheritance, you can derive from what's called a mix-in class to easily add functionality to a type. By implementing custom dynamic types in C#, you can emulate this behavior.

Efficiency

At this point, performance-savvy readers might be getting worried that dynamic just introduces a huge efficiency bottleneck by slowing down each and every dynamic dispatch in the program. Fear not! For each dynamic call analysis, the results are cached in the DLR for later retrieval. Therefore, just like the JIT compiler, you pay the price only the first time around. To demonstrate this, consider the following code, which uses a crude method of timing multiple calls to a method on a dynamic call site:

using System;
using System.Runtime.InteropServices;

class C
{
    public void DoWork() {
        Console.Write( "Doing work...  " );
    }
}

static class EntryPoint
{
    [DllImport("kernel32.dll")]
    private static extern int QueryPerformanceCounter( out Int64 count );

    static void Main() {
        // Let's call DoWork once statically to get it jitted.
        C c = new C();
        c.DoWork();
        Console.WriteLine();

        dynamic d = c;

        for( int i = 0; i < 10; ++i ) {
            Int64 start, end;

            QueryPerformanceCounter( out start );
            d.DoWork();
            QueryPerformanceCounter( out end );
            Console.WriteLine( "Ticks: {0}",
                               end - start );
        }
    }
}

I compiled and ran this example code on a virtual machine running Windows 7 while using the high performance counter to time each dynamic call. Following are the results, which show that the results of the dynamic resolution are cached for later use, thus saving lots of time on subsequent dynamic invocations:

Doing work...
Doing work... Ticks: 83760

Doing work... Ticks: 2161

Doing work... Ticks: 1937
Doing work... Ticks: 1858

Doing work... Ticks: 1845

Doing work... Ticks: 1981

Doing work... Ticks: 1853

Doing work... Ticks: 1834

Doing work... Ticks: 1995
Doing work... Ticks: 1887

I first call DoWork once through a static receiver to make sure the method is JIT compiled before I gather the numbers. That way, the first tick count should not reflect any JIT compiler time.

Boxing with Dynamic

Boxing is one of those areas in which many perils lie. As always, you should be careful when boxing is involved in your code. But how does dynamic handle boxing? It does "the right thing," meaning that it does what you would expect from the spirit of the code. Consider the following code:

using System;

static class EntryPoint
{
    static void Main() {
        dynamic d = 42;
        ++d;

        object o = 42;
        o = (int)o + 1;

        Console.WriteLine( "d = " + d + "
o = " + o );
    }
}

In this example, you have a dynamic instance that contains an integer. Behind the scenes, it is an object that boxes the integer value. In the dynamic case, you can simply invoke the increment operator to modify the value within the dynamic object's box. Right after that, you can see what it takes to perform the same operation on a static boxing object. Essentially, you have to copy the value out of the box, increment it, and then put it back in. You cannot simply use the increment operator on the o variable. But when you use the increment operator on the d variable, the compiler, via the generated call sites, performs the same work as you had to do on the o variable and allows you to simplify the notation.

Note

Although dynamic simplifies the interaction with boxed values, it does not mean that you should become less cautious and cognizant about the implications of boxing. As always, just because a language feature facilitates something does not mean, it's always correct to utilize it.

Dynamic Conversions

Throughout the design and implementation of dynamic types in C# 4.0, the C# team had to find solutions for some seriously tricky problems. Conversions to and from dynamic types is certainly one of those problems. Recall that in C#, there are two types of conversions. They are implicit conversions and explicit conversions. Implicit conversions do not require the casting syntax, although explicit conversions do. Also, recall that for any type, you can define custom implicit and explicit conversion operators. Dynamic expressions add a whole new dimension to conversions, indeed!

Let's consider implicit conversions for a moment. What types should be implicitly convertible to dynamic? It turns out that all types are implicitly convertible to dynamic. The rules are as follows:

  • There exists an implicit conversion from any reference type to type dynamic.

  • There exists an implicit boxing conversion from any value type to type dynamic.

  • There exists an implicit identity conversion from type dynamic to type dynamic.

  • There exists an implicit identity conversion from type object to type dynamic.

  • There exists an implicit identity conversion between constructed types where generic arguments only differ between object and dynamic.

This is as expected because it then allows you to do the things you would expect, such as what is illustrated in the following code:

class C
{
}

static class EntryPoint
{
    static void Main() {
        dynamic d1 = 42;            // Impl. boxing conversion
        dynamic d2 = new C();       // Impl. ref. conversion
        dynamic d3 = d2;            // Impl. ident. conversion
        dynamic d4 = new object();  // Impl. ref. conversion
    }
}

What about when you need to go the other direction? Should instances of dynamic be convertible to any type? Certainly it makes sense for dynamic expressions to be explicitly convertible to static types. For the sake of discussion, think of a dynamic expression as an expression in which a component of the expression forces the entire thing to be handled dynamically. For example, the right side of the equals sign in the following statement is a dynamic expression if the variable d is a dynamic instance:

Double dbl = 3.14 + d;

Now that I have specified what I mean by a dynamic expression, consider this example:

class C
{
}

static class EntryPoint
{
    static void Main() {
        dynamic d = new C();

        // explicit cast back to C reference
        C cObj = (C) d;

        // What happens here???
        string str = d;
    }
}

I create a new instance of C and implicitly cast it to a dynamic reference. Then I explicitly cast the dynamic reference, which is a short dynamic expression, back into a reference to C, which makes sense. But isn't it cumbersome to have to explicitly cast from a dynamic expression back into reference and value types? All that casting can become laborious, especially if the type you're casting to has a long name (which is common for generic types or LINQ-generated types). Besides, all that casting goes against the spirit of dynamic expressions because they are supposed to streamline your code, making it easier to read and understand. And what about the last statement in the preceding code and what does it mean?

As it turns out, the code does compile correctly. In the last statement, the dynamic expression d is explicitly cast into a string reference, which will generate the following exception at run time:

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot
implicitly convert type 'C' to 'string'

That's very cool, indeed. The compiler has performed the explicit cast from dynamic to string without me having to type the casting notation. In reality, I didn't have to use the cast notation when I converted the dynamic expression back into a C reference. If you load the compiled code into Reflector, you will see that it uses a call site to perform an explicit conversion. Is this more than just a convenience?

Implicit Dynamic Expressions Conversion

The C# team realized that in order for dynamic expressions to be truly dynamic, they must be assignable to reference types and value types. Therefore, assignment of dynamic expressions to reference types or value types is syntactically implicit yet performed dynamically at run time. However, there is a clear distinction between dynamic expressions and type dynamic because type dynamic is not implicitly convertible to anything but dynamic. If it were otherwise, it would seriously mess up method overload resolution (a topic covered in the next section).

Note

At one point during the development of C# 4.0, this type of implicit conversion from dynamic expressions to reference types was called assignment conversion. Therefore, if you read blogs and articles on the Internet written during the development of C# 4.0, you might see references to that term.

Dynamic expression conversion comes into play in cases other than just implicitly assigning a dynamic expression into a value or reference type, and vice versa. If a method's body returns a dynamic expression, but the method declaration returns a static type, dynamic expression conversion is used to convert the dynamic instance back into a statically typed instance. There are other cases (such as during array initialization, in yield blocks, and in foreach statements, just to name a few) in which dynamic expression conversions come into play.

Again, implicit conversion of type dynamic to any reference or value type is not possible because of the chaos that would ensue. Take a look at the following snippet of code and you can see why:

class C
{
    static public void Foo( int i ) {}
    static public void Foo( string str ) {}
}

class D { }

static class EntryPoint
{
    static void Main() {
        dynamic d = new D();

        C.Foo( d );
    }
}

If the compiler were to allow type dynamic to be implicitly convertible to anything while deciding which overload of C.Foo to choose, it would fail with an ambiguity. Therefore, the compiler packages up what it knows at compile time into a call site that performs the remainder of the overload resolution at run time. You can see from looking at this code that it will throw an exception at run time because d contains an instance of D, and D instances are not implicitly convertible to either int or string.

When it comes to overload resolution, dynamic did present some tricky problems to the C# team, and they had to come up with some clever ways to solve them. I will explain some of them in the next section.

Dynamic Overload Resolution

Overload resolution was reasonably complicated before the introduction of dynamic. In various other parts of this book, I talked about overload resolution and how it works in the context of class methods, interface definitions, and extension methods. Dynamic types add a new dimension to overload resolution. Recall from the previous section that dynamic instance variables are implicitly convertible only to type dynamic and nothing else. So what should the compiler do when you invoke a method on a static type passing a dynamic argument?

The solution is that any time dynamic is involved in a method invocation, whether the receiver of the call is dynamic or a parameter is dynamic, overload resolution is performed at run time. That's easy! Consider the following code:

using System;

class C
{
    static public void Foo( double dbl, dynamic dyn ) {
        Console.WriteLine( "void Foo( double dbl, dynamic dyn )" );
    }
    static public void Foo( int i, string str ) {
        Console.WriteLine( "void Foo( int i, string str )" );
    }
}

static class EntryPoint
{
    static void Main() {
        dynamic d = "I'm dynamic";
        dynamic d1 = new object();

        C.Foo( 3.1415, d );            // is it a compile-time overload?
        C.Foo( 42, d );                // run-time overload
        C.Foo( 42, d1 );               // run-time overload

        // The following will not compile!
        // C.Foo( "Hello!", d );
    }
}

The first call to C.Foo matches the signature of the first overload perfectly, even though it has dynamic in its call. You might think the compiler would automatically choose the first overload at compile time, but it does not (otherwise, it would be breaking the dynamic overload resolution rule just stated). The second call defers overload selection until run time, even though both parameters are implicitly convertible to the first overload. That is, int is implicitly convertible to double, and dynamic is implicitly convertible to dynamic. Although the behavior of the second call to C.Foo might seem counterintuitive at first because int is implicitly convertible to double and dynamic is implicitly convertible to dynamic, consider the third call to C.Foo (maybe it will make more sense after you see the following results). The output from the code is shown here:

void Foo( double dbl, dynamic dyn )
void Foo( int i, string str )
void Foo( double dbl, dynamic dyn )

You see, even though in the final two calls to C.Foo, the parameters are both implicitly convertible to the first overload of C.Foo, you don't want the compiler to make the choice at compile time. That's because the dynamic instance's type can be inspected at run time and a more precise choice can be made based on that information.

Finally, notice the last call to C.Foo that I have commented out in the code. It will not compile as written. If every call that involves dynamic is resolved at run time, how is this so? The compiler actually has examined the candidate set of methods and is telling you that there is no chance that an overload will be found at run time. So even though the actual choice of overload is determined at run time, the compiler still applies as much logic as possible at compile time to avoid a situation in which a run-time exception is guaranteed.

Note

If you read early material regarding dynamic overload resolution on the Internet, you likely came across the concept of the phantom method. This was a technique the compiler team employed early on for performing overload resolution on static receivers with dynamic parameters. The notion of the phantom method was later abandoned for the current behavior of treating all such calls using dynamic lookup.

Remember, dynamic is implemented internally as a reference to object with an attribute attached. Therefore, you cannot have overloads within a type in which a single parameter position differs only between dynamic and object. For example, the following will not compile:

class C
{
    // Can't do this!!!
    public void DoWork( object o ) { }
    public void DoWork( dynamic d ) { }
}

If you attempt to compile something like this, you will get a compiler error like the following:

Type 'C' already defines a member called 'DoWork' with the same parameter types

Dynamic Inheritance

dynamic brings with it some complexities when it comes to inheritance. Does it make sense to be able to derive from dynamic? Is it possible to derive from a generic base type in which one of the generic arguments is dynamic? And is it possible to implement a generic interface in which one of the generic arguments is dynamic? I will be digging into them in this section, but first let's talk about the things you cannot do with inheritance and dynamic.

You Cannot Derive from dynamic

One thing you cannot do is use dynamic as a base class. Thus, you cannot do the following:

// This will not compile!!!
class C : dynamic
{
}

If you attempt to compile this code, you will get the following compiler error:

error CS1965: 'C': cannot derive from the dynamic type

When you think about the fact that dynamic is replaced with object in the compiled IL code, you might wonder why you cannot derive from dynamic. But even if you could, what does it buy you? It buys you nothing. If dynamic is really object, you still end up inheriting the same implementation of System.Object as if you had explicitly stated object as the base type of C. And because System.Object is the default base type for all types, the extra typing is redundant. Moreover, C is a static type. Therefore, even if you were able to derive from dynamic, the resultant type will be a static type, thus throwing out the dynamic nature anyway. So it makes no sense at all to derive from dynamic.

You Cannot Implement dynamic Interfaces

Recall that at the CLR level, dynamic is nothing more than object with some attributes attached to it. Keeping that in mind, let's consider the following code:

// This will not compile!!!
interface IWork<T>
{
    void DoWork( T item );
}

class C : IWork<dynamic>
{
    public void DoWork( dynamic item ) {
    }
}

If you attempt to compile this code, you will be greeted with the following compiler error:

error CS1966: 'C': cannot implement a dynamic interface 'IWork<dynamic>'

What the compiler is telling you is that you cannot implement a generic interface and specify that the generic argument is type dynamic. Why is this? There are two good reasons. The first reason is a technical one. Currently, in the CLR (which is an implementation of the CLI specification) there is no way to emit the DynamicAttribute attribute, or any attribute for that matter, for the generic argument. To illustrate, look at the following code that also will not compile:

//This will not compile!!!
using System;

class SpecialAttribute : Attribute
{
}

interface IWork<T>
{
    void DoWork( T item );
}

class C : IWork< [Special] object >
{
    public void DoWork( [Special] object item ) {
    }
}

If you attempt to decorate the generic argument with an attribute, you will get the following compiler errors, which show that the compiler has no idea about what you are trying to do because it fails the basic syntax verification:

generic_attribute.cs(13,18): error CS1031: Type expected
generic_attribute.cs(13,35): error CS1519: Invalid token '>' in class, struct, or
interface member declaration

The second reason why you cannot implement dynamic interfaces is practical in nature. If you think about it, just because you cannot do this does not mean that you lose anything. For example, imagine that you use object instead of dynamic and then convert those object instances to dynamic at the point where you operate upon them. You would essentially achieve the same effect. For example, consider this modified code that illustrates the point:

interface IWork<T>
{
    void DoWork( T item );
}

class C : IWork<object>
{
    public void DoWork( object item ) {
        dynamic d = item;

        // Now complete the work with the
        // dynamic thing.
    }
}

static class EntryPoint
{
    static void Main() {
C c = new C();
        dynamic d = new object();

        c.DoWork( d );
    }
}

This example demonstrates that nothing is lost because you cannot implement dynamic interfaces. In the Main method, I can pass a dynamic instance to the DoWork method; inside the DoWork method, I can operate on that dynamic instance even though I was unable to specify type dynamic in the generic arguments where C implements IWork<>. To further illustrate this notion, consider the following example:

using System;
using System.Collections.Generic;

class C
{
}

static class EntryPoint
{
    static void Main() {
        IList<dynamic> myList = new List<dynamic>();

        myList.Add( new C() );
        myList.Add( new object() );

        foreach( dynamic item in myList ) {
            Console.WriteLine( item.GetType() );
        }
    }
}

Notice the type of myList! Just because you cannot implement IList<dynamic> in types does not mean you cannot declare a variable of type IList<dynamic>. This further illustrates the fact that not being able to implement dynamic interfaces is a moot point because you can achieve the same intent regardless. In fact, if you replace every instance of the word dynamic with object in the example, you will get the output shown here:

C
System.Object

You Can Derive From Dynamic Base Types

After all this talk about how you cannot use dynamic as a base type and how you cannot implement dynamic interfaces, you might be surprised that you can derive from generic base types that have dynamic type arguments. So what does that mean? Let's see a short example:

using System;
class B<T>
{
    public T Value { get; set; }
}

class C : B<dynamic>
{
}

static class EntryPoint
{
    static void Main() {
        C c = new C();

        c.Value = "C# Rocks!";
        Console.WriteLine( c.Value.GetType() );
    }
}

So why can you get away with doing this even though types cannot implement dynamic interfaces? Part of the reason is because you can. Remember that in the case of dynamic interfaces there is no way for the compiler to emit the attribute necessary to denote the fact that the generic argument is dynamic. But because a type can inherit at most from only one other type, it is possible to decorate the derived type with the DynamicAttribute type to indicate that one or more of the generic arguments to the base type are dynamic. As you have before, take a look at what class C looks like in Reflector, and you'll see something like the following:

[Dynamic(new bool[] { false, true })]
internal class C : B<object>
{
    // Methods
    public C();
}

Keep in mind that the code generated by the compiler, DynamicAttribute (which decorates class C), has a couple of constructor overloads. This one accepts a type of bool[]. The bool array is used to denote which one of the type arguments is dynamic. For more information, check out the documentation for DynamicAttribute in the MSDN.

Logically, what does it mean to be able to do this and does it buy you anything more than had you simply provided object as the type argument? Actually, it does buy you something. Consider the minor modification to the Main method:

static class EntryPoint
{
    static void Main() {
        C c = new C();

        c.Value = "C# Rocks!";
        Console.WriteLine( 42 + c.Value );
    }
}

The text in bold is what I want you to pay attention to. Because c.Value is a dynamic expression, the expression in the call to Console.WriteLine becomes a dynamic expression. And just like any dynamic expression anywhere else, type resolution is deferred until run time. Moreover, the compiler cannot choose which overload of the addition operator to call without first resolving the types; therefore, it is also deferred until run time. If you execute the Main method, you get the following results:

42C# Rocks!

If you were to replace the occurrence of dynamic with object in the previous example; that is, if you were to make object the type argument in the base type of C, you would get a far different result. In fact, you would get the following compiler error:

error CS0019: Operator '+' cannot be applied to operands of type 'int' and 'object'

Therefore, being able to supply dynamic as a generic type argument in base types is handy in some situations when dynamic expression evaluation at run time is necessary.

Duck Typing in C#

Duck typing is where the type of an object is determined by the contract it supports rather than actual interfaces or base types that it derives from. Duck typing is common in some C++ template libraries, in which where you can do something similar to the following C# code that will not compile:

// This will not compile!!!
class C<T>
{
    static public void DoWork( T item ) {
        item.DoWork();
    }
}

If you attempt this code, you are greeted with the following compiler error:

error CS1061: 'T' does not contain a definition for 'DoWork' and no extension method
'DoWork' accepting a first argument of type 'T' could be found (are you missing a using
directive or an assembly reference?)

Instead, you must use generic constraints to do anything close to the intended effect of the previous code. However, constraints still don't get you duck typing because you are relying upon type definitions. Wouldn't it be nice to be able to say, "whatever type T is, I want to invoke the DoWork method" without having to have T implement an interface that includes a definition for DoWork?

The irony is that the C# compiler does exactly this. Consider the following code:

using System;
using System.Collections;
class C
{
    public IEnumerator GetEnumerator() {
        long l = 0;
        while( l < 10 ) {
            yield return ++l;
        }
    }
}

static class EntryPoint
{
    static void Main() {
        C c = new C();

        foreach( var item in c ) {
            Console.Write( item + ", " );
        }
    }
}

When you execute code, it simply prints out these integers:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

The functionality of the program is not exciting, but what is interesting is the foreach statement in bold. Recall that behind the scenes, the compiler calls GetEnumerator on the collection object on which you want to iterate. And as you probably know, GetEnumerator is part of the IEnumerable and IEnumerable<T> interfaces. However, notice that class C implements neither of these interfaces! It is a common misconception that the type foreach iterates over needs to implement one of the IEnumerable interfaces. Instead, the compiler just compiles in a call to GetEnumerator on whatever instance foreach is iterating over. In fact, if you were to comment out the GetEnumerator method and attempt to recompile, the compiler would tell you the following:

error CS1579: foreach statement cannot operate on variables of type 'C' because 'C' does not
contain a public definition for 'GetEnumerator'

This behavior of the compiler is a perfect example of duck typing at work. After all, the compiler does not care what type is given to foreach or whether it implements some particular interface; instead it just wants that type to implement a specific method with a specific signature. However, prior to C# 4.0, this capability was virtually impossible in code.

Now, let's look at how you can achieve this same result using type dynamic. Imagine that you are adding new features to a very large and mature application. Furthermore, you have identified that during testing it would be extremely handy to be able to dump detailed state information about objects to a debug log by calling a method named DumpStateTo. Because this is a large mature application, there are literally thousands of types defined. Therefore, it is unfeasible due to time constraints to define a new interface and expect all the types to implement it. So let's look at how this could be implemented in C# using dynamic:

using System;
using System.IO;
using Microsoft.CSharp.RuntimeBinder;

class C
{
    public void DumpStateTo( TextWriter tw ) {
        tw.WriteLine( "This is the state for a " +
                      GetType() + " instance" );
        tw.WriteLine( "	Value == " + Value );
    }

    public long Value { get; set; }
}

class D
{
}

static class EntryPoint
{
    static void Main() {
        C c = new C();
        c.Value = 42;

        D d = new D();

        // Now let's dump some debug info
        DumpDebugInfo( c );
        DumpDebugInfo( d );
    }

    static void DumpDebugInfo( dynamic d ) {
        // We don't want a lack of the DumpStateTo() method to
        // crash the application.
        try {
            Console.WriteLine( "--------------------------------" );
            d.DumpStateTo( Console.Out );
        }
        catch( RuntimeBinderException rbe ) {
            Console.WriteLine( "Failed to dump state for: " +
                               d.GetType() );
            Console.WriteLine( "	" + rbe.Message );
        }
    }
}

This example created an instance of both C and D, and you then pass them to DumpDebugInfo, which is a wrapper around calls to DumpStateTo. Notice that DumpDebugInfo achieves duck typing by accepting a parameter of type dynamic. Also, it is very important to catch any runtime binder exceptions because, as stated, this fictional large application has thousands of types that might or might not implement DumpStateTo. The results of the preceding code are shown here:

--------------------------------
This is the state for a C instance

        Value == 42

--------------------------------

Failed to dump state for: D
'D' does not contain a definition for 'DumpStateTo'

In a real-world implementation, you might also want to include other information that would help you identify exactly which instance is dumped so you can find it easily in a debugger.

One of the biggest differences between duck typing in C# using dynamic as opposed to duck typing in some static languages, such as C++ using templates, is that type errors are deferred until run time, whereas in C++ they are discovered at compile time. This is actually a big deal, indeed. You should use duck typing with dynamic sparingly and carefully for the sake of robustness. If you must heavily rely on dynamic duck typing, be sure to implement good error-handling mechanisms. Throughout this book, I have stressed the importance of using the compiler as your friend to catch as many programming errors as possible at compile time rather than run time. That was one of the motivating factors behind implementing generics in C# 2.0. But with dynamic duck typing, you are throwing all that out of the window so you must be prepared to handle the unintended consequences.

Limitations of dynamic Types

The new dynamic type was no easy feat to implement. There are some things you simply cannot do with dynamic. Some of those things just don't make sense, and others do, but the C# team might have not had enough time to implement them properly. Furthermore, just as with any other new feature in a programming language, you will learn more about it and its uses over time while using it. In other words, don't be surprised if the use of dynamic evolves over the coming years as the language matures.

As it stands, you cannot use the extension method syntax with type dynamic in C# 4.0. This might change in future versions, though. As I mentioned before, you also cannot implement dynamic interfaces; that is, interfaces where you specify dynamic as one of the type parameters. Also, you cannot use dynamic in constraint clauses.

ExpandoObject: Creating Objects Dynamically

Up to this point in this chapter, you have seen how the dynamic type facilitates interoperability and how to treat any type instance as a dynamic instance. But what about creating types dynamically at run time?

Since the initial release of the .NET Framework, you have always been able to create code dynamically using the facilities within the System.Reflection.Emit namespace. But doing so is no trivial task. Starting with .NET 4.0, the DLR team provides the System.Dynamic.ExpandoObject, which makes it incredibly easy to create dynamic instances of objects. Let's go ahead and look at an example:

using System;
using System.Dynamic;
using System.Collections.Generic;

static class EntryPoint
{
    static void Main() {
        // Create the kennel
        dynamic dogKennel = new ExpandoObject();

        // Set some useful properties
        dogKennel.Address = "1234 DogBone Way";
        dogKennel.City = "Fairbanks";
        dogKennel.State = "Alaska";

        dogKennel.Owner = new ExpandoObject();
        dogKennel.Owner.Name = "Ginger";

        // Setup a collection of dynamic dogs
        dogKennel.Dogs = new List<dynamic>();

        // Create some dogs
        dynamic thor = new ExpandoObject();
        thor.Name = "Thor";
        thor.Breed = "Siberian Husky";

        dynamic apollo = new ExpandoObject();
        apollo.Name = "Apollo";
        apollo.Breed = "Siberian Husky";

        // Put the dogs in the kennel
        dogKennel.Dogs.Add( thor );
        dogKennel.Dogs.Add( apollo );
    }
}

The first thing to notice is that when I created the new instance of ExpandoObject, I assigned it to a variable of type dynamic that is essential because ExpandoObject implements IDynamicMetaObjectProvider, through which it gets its special powers. Notice that I populated the properties on the object by simply assigning to them as if they already existed. In reality, this operation creates the property and assigns it at the same time. This magic is performed by ExpandoObject's implementation of IDynamicMetaObjectProvider, which adds an entry to an internal dictionary. To create contained objects in the dogKennel object, simply assign a new instance of ExpandoObject to a property name as I did with dogKennel.Owner. If you need your dynamic object to contain a collection of objects, simply assign a new instance of a container object to a new property, as I did when I assigned an instance of List<dynamic> to dogKennel.Dogs. I set the generic argument to dynamic in the collection type because I want the contained objects to also be dynamic objects that I can create with ExpandoObject. I'm sure you will agree that using ExpandoObject to create dynamic object instances is much easier than using System.Reflection.Emit.

What if you want to enumerate the properties of the dynamic instance without having to know what they are ahead of time? For example, what if you need a method named PrintExpandoObject to print the contents of any dynamic ExpandoObject instance to the console? This is easy to do because ExpandoObject implements IDictionary<string, object>, through which you can enumerate the properties contained within the ExpandoObject instance. For example, one implementation for PrintExpandoObject could look like the following:

static void PrintExpandoObject( dynamic obj,
                                string name,
                                int indent = 0 ) {
    Func<int, string> createPad = (n) => {
           return string.Join("", Enumerable.Repeat("   ", n) );
    };

    Console.WriteLine( createPad(indent) + name + ":" );
    ++indent;

    var dict = (IDictionary<string, object>) obj;
    foreach( var property in dict ) {
        if( property.Value is ExpandoObject ) {
            // Recurse to print the contained ExpandoObject
            PrintExpandoObject( property.Value,
                                property.Key,
                                indent );
        } else {
            if( property.Value is IEnumerable<dynamic> ) {
                string collName = property.Key;
                Console.WriteLine( "{0}{1} collection:",
                                   createPad(indent),
                                   collName );
                int index = 0;
                foreach( var item in
                         (IEnumerable<dynamic>)property.Value ) {
                    string itemName =
                        string.Format( "{0}[{1}]",
                                       collName,
                                       index++ );

                    // Recurse for this instance
                    PrintExpandoObject( item,
                                        itemName,
                                        indent+1 );
               }
           } else {
               Console.WriteLine( "{0}{1} = {2}",
                                  createPad(indent),
                                  property.Key,
                                  property.Value );
           }
        }
    }
}

In the example in which I created the dogKennel instance, I could have added the following code afterward:

PrintExpandoObject( dogKennel, "Ginger's Kennel" );

Notice that for each key/value pair within the dictionary I test whether the value is also another instance of ExpandoObject. If so, I make a recursive call into PrintExpandoObject to print it. Likewise, if the value is an enumerable type, I iterate through the enumerable items, assuming that they are instances of ExpandoObject and recurse for them as well. In an attempt to make the output a little bit prettier, I have passed an indention value down through the stack, thus producing output that looks similar to the following:

Ginger's Kennel:
Address = 1234 DogBone Way

   City = Fairbanks

   State = Alaska

   Owner:

      Name = Ginger

   Dogs collection:

      Dogs[0]:

         Name = Thor

         Breed = Siberian Husky

      Dogs[1]:

         Name = Apollo
Breed = Siberian Husky

I have assigned the ExpandoObject to a variable of type dynamic rather than a variable of type ExpandoObject. Although I could have assigned it to variable of type ExpandoObject, it would have meant that the only way to add properties would have been through the methods associated with the IDictionary<string, object> interface. Obviously, that's not as slick as creating the properties on the fly, as already shown. Incidentally, the only way to remove properties from ExpandoObject instances is via the methods associated with the IDictionary<string, object> interface.

Note

When you use ExpandoObject, you often have to perform a certain degree of casting. Of course, such casting could result in thrown exceptions, but such is the nature of deferring the type checking of the compiler to run time.

But what about dynamic methods? So far, I have only shown you how to create properties on ExpandoObject instances via a variable of type dynamic. Actually, it's just as easy to create dynamic methods, too. Here is an instance called dynamicExpression that contains a collection of coefficients for computing a univariate polynomial:

using System;
using System.Dynamic;
using System.Linq.Expressions;
using System.Collections.Generic;

static class EntryPoint
{
    static void Main() {
        dynamic dynamicExpression = new ExpandoObject();

        // Add the coefficients
        dynamicExpression.Coefficients = new List<dynamic>();
        dynamicExpression.Coefficients.Add( 2 );
        dynamicExpression.Coefficients.Add( 5 );
        dynamicExpression.Coefficients.Add( 3 );

        // Create dynamic method
        dynamicExpression.Compute =
            new Func<double, double>( (x) => {
                double result = 0;

                for( int i = 0;
                     i < dynamicExpression.Coefficients.Count;
                     ++i ) {
                    result +=
                        (double)dynamicExpression.Coefficients[i] *
                        Math.Pow( x, (double) i );
                }

                return result;
            } );

        // Let's compute a value now
        Console.WriteLine( dynamicExpression.Compute(2) );
    }
}

I have bolded the area in the code where I create and then call the dynamically created method named Compute. All you have to do is create a delegate instance and assign it to a property on the ExpandoObject instance where the name of the property is the same name you want associated with the method. Then ExpandoObject's implementation of IDynamicMetaObjectProvider allows you to simply call through to that delegate using the familiar method invocation syntax as long as you invoke the method through a variable of type dynamic. In the previous code, I used the Func<> delegate type, along with a lambda expression, to provide the delegate.

Summary

This chapter covered the dynamic type added to the language in C# 4.0. Interoperability is the major theme regarding dynamic types. Now it becomes much easier to interface with dynamic languages such as IronPython and IronRuby, as well as legacy COM automation objects. Code that interacts with those technologies becomes cleaner and clearer. I also showed how you use the ExpandoObject type to create dynamically typed objects at run time. Additionally, C# has finally gained parity with Visual Basic in the ease of interoperability arena.

However, such power often comes with its dangers and dynamic types are no exception. When misused, you can bypass the stringent static type checking of the compiler, thus introducing unwanted bugs lurking in the shadows. Also, working with dynamic types can become slightly tricky in some situations, especially with regard to run-time type conversion and overload resolution.

As with any powerful capability of the language, to use it sparingly and with caution is to use it wisely. For example, when object-oriented languages became all the rage, everyone began using inheritance as if it were the end-all solution. Experience quickly showed that instead, when misused, it creates software that is virtually impossible to maintain. In short, when being dynamic, be wise about it.



[77] The DLR is at the heart of .NET-based dynamic languages such as IronPython and IronRuby. It provides an environment within which it is easy to implement dynamic languages as well as add dynamic capabilities to a statically typed language such as C#. You can read more about the DLR on MSDN.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.137.12