What is the 'dynamic' type in C# 4.0 used for?

The dynamic keyword was added, together with many other new features of C# 4.0, to make it simpler to talk to code that lives in or comes from other runtimes, that has different APIs.

Take an example.

If you have a COM object, like the Word.Application object, and want to open a document, the method to do that comes with no less than 15 parameters, most of which are optional.

To call this method, you would need something like this (I'm simplifying, this is not actual code):

object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing);

Note all those arguments? You need to pass those since C# before version 4.0 did not have a notion of optional arguments. In C# 4.0, COM APIs have been made easier to work with by introducing:

  1. Optional arguments
  2. Making ref optional for COM APIs
  3. Named arguments

The new syntax for the above call would be:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

See how much easier it looks, how much more readable it becomes?

Let's break that apart:

                                    named argument, can skip the rest
                                                   |
                                                   v
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
                                 ^                         ^
                                 |                         |
                               notice no ref keyword, can pass
                               actual parameter values instead

The magic is that the C# compiler will now inject the necessary code, and work with new classes in the runtime, to do almost the exact same thing that you did before, but the syntax has been hidden from you, now you can focus on the what, and not so much on the how. Anders Hejlsberg is fond of saying that you have to invoke different "incantations", which is a sort of pun on the magic of the whole thing, where you typically have to wave your hand(s) and say some magic words in the right order to get a certain type of spell going. The old API way of talking to COM objects was a lot of that, you needed to jump through a lot of hoops in order to coax the compiler to compile the code for you.

Things break down in C# before version 4.0 even more if you try to talk to a COM object that you don't have an interface or class for, all you have is an IDispatch reference.

If you don't know what it is, IDispatch is basically reflection for COM objects. With an IDispatch interface you can ask the object "what is the id number for the method known as Save", and build up arrays of a certain type containing the argument values, and finally call an Invoke method on the IDispatch interface to call the method, passing all the information you've managed to scrounge together.

The above Save method could look like this (this is definitely not the right code):

string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);

All this for just opening a document.

VB had optional arguments and support for most of this out of the box a long time ago, so this C# code:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

is basically just C# catching up to VB in terms of expressiveness, but doing it the right way, by making it extendable, and not just for COM. Of course this is also available for VB.NET or any other language built on top of the .NET runtime.

You can find more information about the IDispatch interface on Wikipedia: IDispatch if you want to read more about it. It's really gory stuff.

However, what if you wanted to talk to a Python object? There's a different API for that than the one used for COM objects, and since Python objects are dynamic in nature as well, you need to resort to reflection magic to find the right methods to call, their parameters, etc. but not the .NET reflection, something written for Python, pretty much like the IDispatch code above, just altogether different.

And for Ruby? A different API still.

JavaScript? Same deal, different API for that as well.

The dynamic keyword consists of two things:

  1. The new keyword in C#, dynamic
  2. A set of runtime classes that knows how to deal with the different types of objects, that implement a specific API that the dynamic keyword requires, and maps the calls to the right way of doing things. The API is even documented, so if you have objects that comes from a runtime not covered, you can add it.

The dynamic keyword is not, however, meant to replace any existing .NET-only code. Sure, you can do it, but it was not added for that reason, and the authors of the C# programming language with Anders Hejlsberg in the front, has been most adamant that they still regard C# as a strongly typed language, and will not sacrifice that principle.

This means that although you can write code like this:

dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;

and have it compile, it was not meant as a sort of magic-lets-figure-out-what-you-meant-at-runtime type of system.

The whole purpose was to make it easier to talk to other types of objects.

There's plenty of material on the internet about the keyword, proponents, opponents, discussions, rants, praise, etc.

I suggest you start with the following links and then google for more:

  • DevDays 2010: Anders Hejlsberg - C# 4.0 and beyond
  • Channel 9: Mads Torgersen - Inside C# 4.0: dynamic typing + +
  • DevX: COM Interop Gets Much Better in C# 4.0
  • Scott Hanselman - C# 4 and the dynamic keyword - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

The dynamic keyword is new to C# 4.0, and is used to tell the compiler that a variable's type can change or that it is not known until runtime. Think of it as being able to interact with an Object without having to cast it.

dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!

Notice we did not need to cast nor declare cust as type Customer. Because we declared it dynamic, the runtime takes over and then searches and sets the FirstName property for us. Now, of course, when you are using a dynamic variable, you are giving up compiler type checking. This means the call cust.MissingMethod() will compile and not fail until runtime. The result of this operation is a RuntimeBinderException because MissingMethod is not defined on the Customer class.

The example above shows how dynamic works when calling methods and properties. Another powerful (and potentially dangerous) feature is being able to reuse variables for different types of data. I'm sure the Python, Ruby, and Perl programmers out there can think of a million ways to take advantage of this, but I've been using C# so long that it just feels "wrong" to me.

dynamic foo = 123;
foo = "bar";

OK, so you most likely will not be writing code like the above very often. There may be times, however, when variable reuse can come in handy or clean up a dirty piece of legacy code. One simple case I run into often is constantly having to cast between decimal and double.

decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");

The second line does not compile because 2.5 is typed as a double and line 3 does not compile because Math.Sqrt expects a double. Obviously, all you have to do is cast and/or change your variable type, but there may be situations where dynamic makes sense to use.

dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");

Read more feature : http://www.codeproject.com/KB/cs/CSharp4Features.aspx


I am surprised that nobody mentioned multiple dispatch. The usual way to work around this is via Visitor pattern and that is not always possible so you end up with stacked is checks.

So here is a real life example of an application of my own. Instead of doing:

public static MapDtoBase CreateDto(ChartItem item)
{
    if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
    if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
    if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
    //other subtypes follow
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

You do:

public static MapDtoBase CreateDto(ChartItem item)
{
    return CreateDtoImpl(item as dynamic);
}

private static MapDtoBase CreateDtoImpl(ChartItem item)
{
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

private static MapDtoBase CreateDtoImpl(MapPoint item)
{
    return new MapPointDto(item);
}

private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
    return new ElevationDto(item);
}

Note that in first case ElevationPoint is subclass of MapPoint and if it's not placed before MapPointit will never be reached. This is not the case with dynamic, as the closest matching method will be called.

As you might guess from the code, that feature came handy while I was performing translation from ChartItem objects to their serializable versions. I didn't want to pollute my code with visitors and I didn't want also to pollute my ChartItem objects with useless serialization specific attributes.