动态,linq和Select()

mat*_*ieu 13 c# linq dynamic c#-4.0

考虑以下(无意义,但仅用于说明目的)测试类:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么不编译时出现以下错误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?)
Run Code Online (Sandbox Code Playgroud)

第二种方法没有错误.

Jon*_*Jon 11

我相信这里发生的是因为表达式ToStr(x)涉及一个dynamic变量,整个表达式的结果类型也是dynamic; 这就是为什么编译器认为它有一个IEnumerable<dynamic>预期的地方IEnumerable<string>.

public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
    return t.Select(x => ToStr(x));
}
Run Code Online (Sandbox Code Playgroud)

有两种方法可以解决这个问题.

使用显式强制转换:

public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
    return t.Select(x => (string)ToStr(x));
}
Run Code Online (Sandbox Code Playgroud)

这告诉编译器表达式的结果肯定是一个字符串,所以我们最终得到一个IEnumerable<string>.

用方法组替换lambda:

public IEnumerable<string> ToEnumerableStrsWontCompile(IEnumerable<dynamic> t)
{
    return t.Select(ToStr);
}
Run Code Online (Sandbox Code Playgroud)

这样编译器会隐式地将方法组表达式转换为lambda.请注意,由于表达式中没有提及dynamic变量x,因此可以立即推断其结果的类型,string因为只有一种方法需要考虑,其返回类型是string.

  • +1表示解释,特别是方法组版本 (2认同)