views:

82

answers:

2
public string Foo(object obj) {
    return null;
}

public string Foo(string str) {
    return null;
}

var x = Foo((dynamic) "abc");

Why is x dynamic, compiler not smart enough or I miss something important?

+3  A: 

I'm just guessing here, but...

When you add a cast to dynamic, the entire expression becomes a dynamic expression. The result of a dynamic expression is always going to be dynamic because everything is resolved at run-time.

Check out the MSDN page on using dynamic for more info:

Using Type dynamic (C# Programming Guide)

And scroll to the following text:

The result of most dynamic operations is itself dynamic.

Justin Niessner
Yes, but this compiles just fine: `string x = Foo((dynamic)"abc");`
Darin Dimitrov
Why is it need to be resolved at run-time, if all methods return string?
dotneter
@Darin - Check out the link I posted. It also covers implicit conversions of dynamic back to static types. Look for: "Conversely, an implicit conversion can be dynamically applied to any expression of type dynamic." In this case, the result of the expression is still dynamic but since you declare x as a static type it is implicitly converted back.
Justin Niessner
@Justin: Seems we're arguing the same point here, so I'll let you do the work and get the votes :)
Brian Rasmussen
@Justin, yes but here the variable at the right hand side is not dynamic. It is a static function call. What is dynamic is the argument passed to this function. The Foo function is totally static. Pressing F12 while hovering the cursor over it, directly moves to the definition meaning that the compiler knows this function. If you were calling the Foo function over a dynamic type variable, then I agree that the compiler doesn't know of it's existence.
Darin Dimitrov
@Darin - The expression on the right hand side becomes a dynamic expression as soon as the dynamic type is introduced (as the quote from MSDN dictates and the language spec dictates).
Justin Niessner
So, why doesn't this become dynamic: `string x = Foo((dynamic)"abc");`?
Darin Dimitrov
@Darin - Because there is an implicit cast (from dynamic back to string) that is dynamically applied to the result of the dynamic expression (which is also covered in the MSDN docs).
Justin Niessner
@Justin, my head will explode. I cannot follow this anymore :-) You seem pretty confident and I guess you are right.
Darin Dimitrov
@Darin - ...I never did like dynamic types. :-P I think this is one of those times that one of the C# Language guys needs to hop in and validate. Where's Eric when you need him? Haha.
Justin Niessner
@Justin, yes C# compiler is treating the function call as dynamic call site but it need not be in this case. It could have resolved it statically unless it is assuming the rare scenario of runtime code injection :-) But as you said, only Eric L could answer the reasoning behind this decision.
VinayC
My understanding is the same as Justin's. The expression `Foo((dynamic)"abc")` is always dynamic as far as the compiler is concerned, because the compiler doesn't try to do overload resolution on methods with arguments of dynamic type. But you can assign dynamic expressions to string variables, so `string x = [some dynamic expression]` is legal as far as the compiler is concerned. If your dynamic expression doesn't end up having a value you can put in `string x`, it's a run-time error.
Tim Goodman
From the blog posting I linked in my answer, note that there is an implicit conversion from dynamic expressions to any type -- but not from the dynamic type itself to any type. The distinction is made clear in the blog.
Tim Goodman
+3  A: 

This blog posting might be helpful to you: http://blogs.msdn.com/b/cburrows/archive/2010/04/01/errata-dynamic-conversions-and-overload-resolution.aspx

In particular: "If you have a method call with a dynamic argument, it is dispatched dynamically, period."

That means C# doesn't know which overload is being called until runtime. It doesn't know at compile time. My understanding is that it doesn't even check what the possible overloads are at compile time (why would it?), or make a note of the fact that in your case they all return strings.

So at compile time, the return value of Foo isn't known. Thus the type of x is determined at compile time to be dynamic.

Tim Goodman