Considering the following (pointless, but it’s for illustration purpose) test class :
public class Test
{
public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
return t.Select(x => ToStr(x));
}
public IEnumerable<string> ToEnumerableStrsWillCompile(IEnumerable<dynamic> t)
{
var res = new List<string>();
foreach (var d in t)
{
res.Add(ToStr(d));
}
return res;
}
public string ToStr(dynamic d)
{
return new string(d.GetType());
}
}
Why doesn’t it compile with the following error, on t.Select(x => ToStr(x)) ?
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<dynamic>'
to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion
exists (are you missing a cast?)
No error on the second method.
I believe what happens here is that since the expression
ToStr(x)involves adynamicvariable, the whole expression’s result type is alsodynamic; that’s why the compiler thinks that it has anIEnumerable<dynamic>where it expects anIEnumerable<string>.There are two ways you can fix this.
Use an explicit cast:
This tells the compiler that the result of the expression is definitely going to be a string, so we end up with an
IEnumerable<string>.Replace the lambda with a method group:
This way the compiler implicitly converts the method group expression to a lambda. Note that since there is no mention of the
dynamicvariablexin the expression, the type of its result can be immediately inferred to bestringbecause there is only one method to consider, and its return type isstring.