var array = new [] {d, "hello"} is implicitly typed to dynamic[] and not string[] ? why?

dynamic d = 5;
var array = new[] {d,"hello"}

What is the implicit type of array ? It is dynamic[] but not string[], why ?

While going through C# in depth - Jon Skeet stated a rules for dynamic conversions :

An implicit conversion exists from any expression of type dynamic to almost any CLR type

Later on he mentioned that he purposely said conversion from an "expression of type dynamic" but not from dynamic type itself.

You may have also noticed that I wrote about a conversion “from an expression of type dynamic” to a CLR type, not a conversion from the dynamic type itself. This subtlety helps during type inference and other situations that need to consider implicit conversions between types

I am bit confused or probably lacking something very basic, but this explains why array type turned out to be dynamic[] and not string[]. Can someone help me understand what he actually meant.

Jon Skeet

For the most part, you can ignore this detail. But if you look through the specification, you'll see various place that the language considers conversions from type X to type Y. There are other places that the language considers conversions from an expression e to type T, usually with some restrictions on the exact expression.

The simplest example of this would be for constants. There's no implicit conversion from int to byte, but there is an implicit conversion from "a constant expression of type int and with a value within the range of byte" to byte.

Similarly there's no conversion from dynamic to string (for example) but there is a conversion from "an expression with a static type of dynamic" to string.

This can be important for things like implicitly typed arrays. Consider this expression:

dynamic d = GetSomeDynamicValue(); // Compiler doesn't know or care actual value
var array = new[] { "hello", d };

What should the type of array be? It ends up being dynamic[], not string[] - which I believe is due to the difference in the kind of conversion. That's just like this:

byte b = 10;
var array = new[] { b, 10 };

... ends up being an int[] even though there's an implicit conversion from the constant expression 10 to byte.

Bottom line: type inference is a really, really hairy bit of the spec. There are these two different kinds of conversion, and it's worth being aware of them, but most of the time you won't need to worry.


See more on this question at Stackoverflow