Timmy's Blog

C# 4.0 - About the dynamic keyword

 

18/11/2008 15:47:13

One of the most important changes in the upcoming C# 4.0 is the "dynamic" type.
You can find information and code samples on the subject all over the web,
so I'm not going to delve to deep into the subject here, but instead I want explain the
difference between the "object" type, the "dynamic" type and the "var" keyword.


First of all it's important to understand "dynamic" is a type and not a keyword.
In a way it is very similar to the "object" type in the sense that you can asign
an instance of any type to it. The difference is that method calls and properties
are resolved at runtime instead of compile time.

The "var" keyword, which is not a type, is a totally different beast.
Unlike what many people think, it is not similar to the var keyword from
dynamic languages such as JavaScript.

When you use the "var" keyword to declare a variable the type is infered
from the assignment that follows the declaration and cannot be changed.

I can't stress this enough: A variable declared using the "var" keyword is statically typed!

Sounds confusing? Let's explain all this using a few examples.

Consider the following code sample:

string helloString = "Hello World";
Console.WriteLine(helloString.Substring(0,5));

This code will compile perfectly. The "Substring" method of the string instance is resolved
at compile time and the output will be "Hello".

Let's try it again, but this time declare helloString as an instance of the "object" type:

object helloString = "Hello World";
Console.WriteLine(helloString.Substring(0,5));

The "object" type does not have a Substring() method and since the method call is resolved
at compile time, compilation will fail.

This time we'll use the var keyword to declare the helloString variable:

var helloString = "Hello World";
Console.WriteLine(helloString.Substring(0,5));

This will compile just fine. The type of helloString is infered by the compiler so by the time
it reaches the second line of code, it already knows helloString is a "string".
Once a variable has been declared using the "var" keyword, its type cannot be changed.
This is also the reason you cannot declare a variable using the "var" keyword without initializing it immediatly.

The following will result in a compiler exception:

var helloString = "Hello World";
helloString = 4; //Cannot change the type!

Since helloString is an instance of "string", you cannot assign an integer to it.
In this example, the only benifit you gain from using the "var" keyword is that you write
less redudant code. Consider the following two lines of code:

//Create an instance of the LightLinkController class
LightLinkController controller = new LightLinkController();

//This does exactly the same
var controller = new LightLinkController();

The result is exactly the same in both cases, but the second method is, in my opinion, easier
to read. We know it's an instance of the LightLinkController class by looking at the initializer.

In reality the "var" keyword was introduced to support anonymous types,
which is a different subject all together.

And finally, let's try our sample with the dynamic keyword:

dynamic helloString = "Hello World";
Console.WriteLine(helloString.Substring(0,5));

This will compile just fine. The compiler does not resolve the Substring() call on our
helloString variable, it leaves that up to the runtime. At runtime the call will be resolved
and as the "String" class has a Substring() method with the specified parameters it'll work fine.

Since the compiler does not resolve method calls or properties at runtime,
the following code will compile just fine:

dynamic helloString = "Hello World"; 
Console.WriteLine(helloString.Translate("nl-BE"));

At runtime however, an exception will be thrown as the "String" class does not expose
a method called "Translate". The following will also compile without problems:

dynamic helloString = "Hello Dynamic World";
helloString = 4;
Console.WriteLine(helloString);

At runtime, by the time the "WriteLine" method is called, helloString will be an instance of int,
and since int32 derives from the "object" class it exposes a method called ToString()
which is called by the WriteLine method, so the code will execute without any problems.

This is why the "dynamic" type is a lot like the "var" keyword in JavaScript.

Of course these examples should not be considered good coding practice,
because this isn't why the dynamic keyword was added. It was added to be
able to interop with dynamic languages and it facilitates Office Interop and reflection.
(If you have ever done any Office Interop, you probably know what a PITA it is).

The following is a (slightly modified) snippet of code from one of my projects:

//C# 3.0 version
compositeType = plugin.CompositeType;
MethodInfo method = compositeType.GetMethod("Compose");
var commands = (List<Command>)method.Invoke(compositeInstance,null);

//C# 4.0 version
dynamic compositeInstance = plugin.CompositeInstance
var commands = (List<Command>)icompositeInstance.Compose();

Sure, it only saves me a single line of code, but the C# 4.0 code is far less complex.

As for the "var" keyword, maybe the C# team should have chosen another keyword,
such as "infered". It would have avoided anger and confusion in the .NET world.

Many people confuse it with the JavaScript "var" keyword and consider it to be evil.
I have heard of managers simply banning its use, which means two things:

1. They did not do their homework and are therefore "outdated"
2. They miss out on all the cool stuff such as anonymous types and to some extend, LINQ.

So to sum things up:

The "object" type

Is the ultimate base class of all .NET classes.
Members are resolved at compile time.

The "dynamic" type

Is statically typed at compile time, dynamically typed at runtime.
Members are resolved at runtime.
Facilitates interop with dynamic languages, Office Interop, Reflection, etc...

The "var" keyword

Has nothing to do with the "var" keyword from dynamic languages.
Is statically typed.
Allows the use of anonymous types.
Is NOT pure evil

That's it. It might all seem a bit vague, but as you start playing with it, you'll understand.
And if I run into a real life problem where I can use the dynamic type, I'll post it.


 
Your comments:
Your details:
 
   
 

Since you have not authenticated,
we require you to submit some
additional information and fill out the captcha.

Your e-mail address will not be disclosed to anyone and will not be visible on the site. If you specify your blog, we will display a link to it.

If you sign in with your OpenID, you can store your profile and you will never have to enter your details or fill in the captcha again.