You've encountered dynamic contagion. A dynamic
could be anything, so any method or property on it could return anything. Any method you pass it to could be anything, because when you pass a dynamic
as a parameter, overload resolution happens at runtime (this can be exploited if you hate the people who'll have to maintain your code).
If you hover the mouse over Select
, it's of type Select<dynamic, string>
, so it returns IEnumerable<String>
. Because ToString(dynamic d)
has an explicit cast to string
in the return
, and returns type string
, the compiler can be assured that ToString
really is returning a string.
IEnumerable<string> test = tmp.Select(ToString);
Incidentally, if we make these changes to ToString(), the above will still compile and the lambda version still won't:
static string ToString(object d)
{
// Remove the cast to string
return d.ToString();
}
The contagion is introduced when we create tmp
as List<dynamic>
.
In lambda version that won't compile, hovering the mouse shows that we're actually calling Select<dynamic, dynamic>
which returns IEnumerable<dynamic>
.
Overload resolution is done at runtime when you pass dynamic
. The compiler can't guarantee at compile time what method will actually be called or what it will return. Intellisense thinks ToString
is your static method, but the compiler doesn't trust that to remain true.
IEnumerable<string> test2 = tmp.Select(x => ToString(x));
This compiles, because we have a cast where overload resolution won't affect it.
IEnumerable<string> test3 = tmp.Select(x => (string)ToString(x));
Jonathon Chase kindly notes in comments that we make it compile by explicitly passing type parameters to Select
:
IEnumerable<string> test4 = tmp.Select<dynamic, string>(x => ToString(x));
The important question, in my view, is why your first case compiles. My cautious guess is that because you're passing a reference to the method rather than calling it, dynamic overload resolution doesn't happen.
Consider this a placeholder until somebody with deeper understanding takes an interest in the question.