views:

184

answers:

5

Does defining an instance as dynamic in C# mean:

  1. The compiler does not perform compile-time type checking, but run-time checking takes place like it always does for all instances.

  2. The compiler does not perform compile-time type checking, but run-time checking takes place, unlike with any other non-dynamic instances.

  3. Same as 2, and this comes with performance penalty (trivial? potentially significant?).

A: 

As far i undesrtand dynamic it only bypasses compile time check. resolution of type happens at runtime as it does for all types. so i dont think there is any performance penalty associated with it.

Vinay B R
The two are far from each other at runtime with a performance hit. E.g. With dynamic the compiler needs to make method overload resolution to see which method to Call and fail if it doesn't find any
Rune FS
+1  A: 

Declaring a variable as dynamic is similar to declaring it as object. Dynamic simply gets another flag indicating that member resolution gets deferred to run-time.

In terms of the performance penalty - it depends on what the underlying object is. That's the whole point of dynamic objects right? The underlying object can be a Ruby or Python object or it can be a C# object. The DLR will figure out at run-time how to resolve member calls on this object and this resolution method will determine the performance penalty.

Having said that - there definitely is a performance penalty.

That's why we're not simply going to start using dynamic objects all over the place.

Jaco Pretorius
There are a few notable difference such as there's only four methods you Can call when declaring as object and I'd be (unless customized binding is in play) if the type of the object played a significant role in the perormance penalty
Rune FS
+6  A: 

As far as I know, the answer is 3.

You can do this:

dynamic x = GetMysteriousObject();
x.DoLaundry();

Since the compiler does no type checking on x, it will compile this code, the assumption being that you know what you're doing.

But this means extra run-time checking has to occur: namely, examining x's type, seeing if it has a DoLaundry method accepting no arguments, and executing it.

In other words the above code is sort of like doing this (I'm not saying it's the same, just drawing a comparison):

object x = GetMysteriousObject();

MethodInfo doLaundry = x.GetType().GetMethod(
    "DoLaundry",
    BindingFlags.Instance | BindingFlags.Public
);

doLaundry.Invoke(x, null);

This is definitely not trivial, though that isn't to say you're going to be able to see a performance issue with your naked eye.

I believe the implementation of dynamic involves some pretty sweet behind-the-scenes caching that gets done for you, so that if you run this code again and x is the same type, it'll run a lot faster.

Don't hold me to that, though. I don't have all that much experience with dynamic; this is merely how I understand it to work.

Dan Tao
Quick question which is not relevant to this question tho but What's `BindingFlags` used for?
Braveyard
@Braveyard: It's basically a set of flags used to specify what characteristics apply to a certain reflected member. In the example above, the relevant characteristics are that it is a public instance member. If `DoLaundry` were a static method, for example, the above code would not find it (you'd need to add `BindingFlags.Static`).
Dan Tao
@Dan Tao -- Thanks for the quick tip.
Braveyard
Things get a bit more complicated too if a dynamic object is passed as an argument to a function that takes non-dynamic perameters, especially one that has multiple overloads.
Jeff M
@Timwi: Good call -- I was honestly taking a shot in the dark. In retrospect, guessing the JIT compiler really didn't make much sense.
Dan Tao
+1  A: 

Well, the variable is statically typed to be of the type dynamic but beyond that the compiler doesn't do any checking as far as I know.

Type binding is done at runtime and yes, there's a penalty, but if dynamic is the only option then so what. If you can solve the problem using static typing do so. That being said, the DLR does call site caching which means some of the overhead is reduced as the plumbing can be reused in some cases.

Brian Rasmussen
+7  A: 

The question is very confusing.

Does defining an instance as dynamic in C# mean:

By "defining an instance" do you mean "declaring a variable"?

The compiler does not perform compile-time type checking, but run-time checking takes place like it always does for all instances.

What do you mean by "run-time checking like it always does"? What run-time checking did you have in mind? Are you thinking of the checking performed by the IL verifier, or are you thinking of runtime type checks caused by casts, or what?

Perhaps it would be best to simply explain what "dynamic" does.

First off, dynamic is from the perspective of the compiler a type. From the perspective of the CLR, there is no such thing as dynamic; by the time the code actually runs, all instances of "dynamic" have been replaced with "object" in the generated code.

The compiler treats expressions of type dynamic exactly as expressions of type object, except that all operations on the value of that expression are analyzed, compiled and executed at runtime based on the runtime type of the instance. The goal is that the code executed has the same semantics as if the compiler had known the runtime types at compile time.

Your question seems to be about performance.

The best way to answer performance questions is to try it and find out - what you should do if you need hard numbers is to write the code both ways, using dynamic and using known types, and then get out a stopwatch and compare the timings. That's the only way to know.

However, let's consider the performance implications of some operations at an abstract level. Suppose you have:

int x = 123;
int y = 456;
int z = x + y;

Adding two integers takes about a billionth of a second on most hardware these days.

What happens if we make it dynamic?

dynamic x = 123;
dynamic y = 456;
dynamic z = x + y;

Now what does this do at runtime? This boxes 123 and 456 into objects, which allocates memory on the heap and does some copies.

Then it starts up the DLR and asks the DLR "has this code site been compiled once already with the types for x and y being int and int?"

The answer in this case is no. The DLR then starts up a special version of the C# compiler which analyzes the addition expression, performs overload resolution, and spits out an expression tree describing the lambda which adds together two ints. The DLR then compiles that lambda into dynamically generated IL, which the jit compiler then jits. The DLR then caches that compiled state so that the second time you ask, the compiler doesn't have to do all that work over again.

That takes longer than a nanosecond. It takes potentially many thousands of nanoseconds.

Does that answer your questions? I don't really understand what you're asking here but I'm making a best guess.

Eric Lippert