What is the difference between “dynamic” and “object” keywords?

What is the difference between “dynamic” and “object” keywords?

Rate This

Let’s take a quick look at the object keyword first. I’m not going to talk a lot about it because it’s been around since C# 1.0. This keyword is nothing more than a shortcut for System.Object, which is the root type in the C# class hierarchy. (However, as Eric Lippert pointed out in his blog post, not everything in C# derives from object.) This is a powerful mechanism, since you can assign almost any value to instances of this type.

Here is a short example that demonstrates some of the benefits and problems of using the object keyword.

object obj = 10;
Console.WriteLine(obj.GetType());
// Prints System.Int32 because
// this is the type of the value stored in this object.

// A compiler error, because
// at compile time the type of obj is System.Object.
// obj = obj + 10;

// You need to explicitly cast obj to a necessary type.
obj = (int)obj + 10;

// However, this does not mean that you are really safe.
// You can cast to a wrong type
// and the compiler will not detect it.
// Here you get an exception at run time,
// because obj is an integer, not a string.
// obj = (string)obj + 10;

// You also get a run-time exception
// if you cast to a wrong numeric type,
// even if there is an implicit conversion in the language.
// obj = (double)obj + 10;

As you can see, although obj stores an integer, the compiler does not let you to perform any mathematical operations without a cast. It may look like casting helps you to ensure that you really have an integer, but it doesn’t. You can cast to a completely different type and the compiler will not detect it. As a result, you get a run-time exception.

So you have to perform an explicit cast that does not guarantee anything just because the compiler doesn’t let you to run your program without a cast.

Here is where the new dynamic keyword in C# 4.0 comes in. It tells the compiler not to enforce additional rules upon your code.

dynamic dyn = 10;
Console.WriteLine(dyn.GetType());
// Same as "object".
// Prints System.Int32 because
// this is the type of the value stored in this object.

// No compiler error, because
// the compiler does not try to identify
// the type of the dynamic object at compile time.
dyn = dyn + 10;

// Also, this operation will succeed for all numeric
// or other types that support a “+” operation.
dyn = 10.0;
dyn = dyn + 10;

dyn = "10";
dyn = dyn + 10;

This is one of the main differences between object and dynamic – with dynamic you tell the compiler that the type of an object can be known only at run time, and the compiler doesn’t try to interfere. As a result, you can write less code. And I want to emphasize that this is no more dangerous than using the original object keyword. However, it is not less dangerous either, so all the type-checking techniques that you need to use when operating with objects (such as reflection) have to be used for dynamic objects as well.

The next question that often comes up is something like the following: “Since a dynamic object can be anything and the compiler doesn’t check what it is, does it mean that you can pass a dynamic object to my unsuspecting method/system and make it crash?”

Let’s assume we have a simple method.

public static void Print(string arg)
{
    Console.WriteLine(arg);
}

Now let’s look at how you can pass a dynamic object to it.

dynamic dyn = 10;

// You get an exception at run time here.
Print(dyn);

As you can see, although the compiler allows you to pass a dynamic object to your method, your method never gets this object if it has a wrong type. An exception is thrown before the method is actually called. The only way you can pass a dynamic object to your method is if it contains a necessary value, in this case, a string.

dynamic dyn = "10";
Print(dyn);

Again, this is not that much different from the behavior you get with the object keyword.

object obj = 10;

// Doesn't compile.
//Print(obj);

// Compiles, but there is an exception at run time.
//Print((string)obj);

// This code works because obj is now a string,
// but you still need a cast.
obj = "10";
Print((string)obj);

Some people say that it isn’t hard to read (int)obj, so why bother with dynamic? Well, there are situations when you have to perform so many cast operations that it makes your code almost unreadable. There are also situations when a simple cast is not enough and you have to call reflection methods, such as InvokeMember or GetProperties. A good example here is COM interop, which is why it was modified to use the new dynamic features (for more information, look at this “how-to”.)

Also, the dynamic keyword and dynamic language runtime enable many scenarios that were either impossible or difficult to do before, including interoperation with dynamic languages. I have highlighted couple of such scenarios earlier on this blog: Introducing ExpandoObject and Creating Wrappers with DynamicObject.

You may also want to take a look at the MSDN walkthrough that shows how you can call an IronPython library from C# and Visual Basic, and a really cool presentation, Using Dynamic Languages to Build Scriptable Applications, by Dino Viehland. Another good presentation that shows some examples and explains the design principles behind this feature is Dynamic Binding in C# 4 by Mads Torgersen.

The conclusion is that there is no need to fear that someone can break your code by using dynamic features. It is no more (and again, no less) dangerous than the object keyword.

So, if you often use the object keyword and have to perform a lot of casting and/or use reflection to call methods and properties of objects, you probably should take a look at the dynamic keyword. In some cases it’s more convenient than object and with less code to write.

Leave a Comment
  • Please add 7 and 6 and type the answer here:
  • Post
  • Well written! and thanks for the explanation.

  • What can you say about boxing/unboxing with dynamic types? Are these aspects also present?

  • This is a very bad idea.  I understand the desire to improve COM interop.  However, a number of developers, particularly those coming from languages such as PHP, are going to abuse this.  

    And we are going to end up in a world of hurt with all of the run time issues this will cause.  Please stop this.  

    Further don't tell me it is 'no more dangerous' than using the object keyword.  It is obviously much more dangerous because you are bypassing one of the first lines of defense against bad code: compile time checking.

  • Re: Chris Lively

    Completely agree. Dynamic is the last nail in the coffin. C# is no longer a serious statically typed language but a language that tries to be everything to all people, yet does nothing really well.

    Kind of sad, actually. Thank god there are new languages such as scala that are more orthogonal and do not compromise type safety.

  • Dynamic can be risky if you abuse of it, but it doesn't mean that it makes the language bad. Actually, it makes it better.

    Just read enough and you'll write good code.

  • "just read enough and you'll write good code"

    Not so much. Compile-time type checking is one of the hallmarks of a great statically-typed language. Those of us that come from an application development background (as opposed to hacking together borrowed scripts to make a WebS1t3) understand the value of this. Introducing and encouraging the use of variants as documented here erodes the quality of code produced by the C# community, and invites bad practices that ravage PHP source bases.

  • This is a BAD idea. If you need dynamic typing at run time use ruby or php or something.

    C# was supposed to be a better mouse trap than C++ which was supposed to a better mouse trap than C which was written as a joke.

    C originally lacked control over typing (void *) and a LOT of people got in deep trouble with it.

  • Re: J

    "Just read enough and you'll write good code." I 100% agree with that.  

    However, a lot of dev's don't read.  And the ones that do have a hard time understanding.  Coding is hard.  That's not necessarily a problem with the languages available, rather it's an issue with the type of thought required to build good stuff.  Further complicating this is that most developers either don't stay in this long enough to be good at it or they simply get caught in a rut and maintain the same thing for 20 years.

    Whenever language designers introduce short cut features then people will jump on it, build products, and spend years getting bit before finally learning what a really really bad idea it was.  In this case the feature is ostensibly to solve issues with COM interop.  In my mind you do not introduce a long term feature that is going to be impossible to pull out in order to solve a short term problem.

    COM Interop is a short term problem.  Windows is moving entirely to managed code, it has to.  COM at some point will finally be completely eradicated.  However we will still have this "dynamic" keyword with us for as long as C# is around.  Further each year will bring new people to the language that don't understand how bad a thing it really is and will abuse it like they have the var keyword; only it's worse due to the lack of compile time checking.  

    This is turn will lead to a wider frustration with the language and large numbers of people will bit shift to something else.  Which leaves us with two options.  Either fix interop itself, which I'm guessing they can't do; or, leave it alone and the problem will quietly go away.  Very few dev's have to deal with COM anyway.  Whereas ALL of them will be exposed to this Dynamic garbage.

  • I disagree that dynamic is a bad idea. It's just another tool in your arsenal. If you don't want to use it, don't. Having done way too much COM interop, it's a welcome addition to the language.

    Additionally, being able to script my C# code via Iron* is a very nice benefit!

  • Now I wonder whether I was clear enough in the post. The main points of this particular article are quite simple:

    a) C# already has the "object" keyword and by using this keyword you can fool any compile-time checking mechanisms.

    b) Many of the scenarios were available in C# even before dynamic keyword was introduced. Dynamic just made them simpler.

    c) There are new scenarios and benefits, of course. But once again, considering that "object" was always there, you should not be afraid that someone using dynamic objects will break your code.

    I am not encouraging "everybody" to start using "dynamic" everywhere in the code. But I would recommend this feature to heavy users of reflection, COM interop (or other interops) and of course those, that already use "object" a lot.

  • There we go again. A new feature. Cry. Cry. Cry.

    Come on! GOTO and IF statements can also be abused, as much as anything else. If you allow improper code to make it into your software you only have yourself to blame. At least use tools like FxCop for your own sake.

    It's not like InvalidCastException is something new in C#4. Dynamic actually removes a whole bunch of cases where instead of getting a runtime exception it will actually perform implicit type conversions.

    I'm just not sure why it won't do so when passing a dynamic as a parameter, but I suppose overload resolution has a lot to do with that. I think that as long as the value is only set internally, it could be checked at compile time. Of course this is not possible in com interop scenarios.

    In any case, dynamic is further reducing the gap. C# is evolving in the right direction. Thanks!

    Happy coding!

    Alex G

  • *Sides with Alexandra* ... Go Alex camp!

    Ok... John can come too! We'll do like the spartans :)

  • Alexandra,

    While I thought your article was good, I do not like your conclusions.  I agree with the majority of what has been voiced here.

    The dynamic keyword is a bad idea.  I didn't think var was a bad idea and I've defended its use when appropriate.  However, dynamic is just ripe for abuse in C#.  C# isn't a dynamic language and shouldn't try to be.

    As far as your latest comments:

    (a) I disagree with your assertion that you can fool "any" compile time checking.  For one, the programmer has to be explicit about what they're trying to do.  Casting to an int from a double or vice versa will throw an exception and it'll be very clear why.  However, what won't be clear is the first time you try to debug an instance of evil type coercion that only occurs based on certain input.

    (b) Simpler isn't always better.  And the dynamic keyword boldy underscores that.

    (c) I'm sorry, but you're just wrong here.  Working with what is for all intents and purposes a base type is not the same as working with what is essentially the same as a Variant from VB.  To this day I deal with crap written with Variants -- someday I'll have it all cleaned up.

    I am putting in force a rule that will not allow the use of the dynamic keyword.

  • Simple and clear article.

    About the debate of dynamic keyword. It is legit and defintely usefull for many programmers, not only because easy, because have its value, mostly in interop area. I don't think any serious programmer or corporation will abuse this.

  • Pretty useful. Definitely dangerous as others have noted, but for situations where type safety is already impossible, it is great to have some shorthand available.

    I've been using "var" definitions in 3.5 like crazy.

Page 1 of 9 (130 items) 12345»