奇数行为随var,dynamic和linq组合而变化

Joa*_*son 5 c# linq var dynamic

我(懒惰地)var在下面的代码的原始版本中使用并在代码的完全不同的部分中获得了奇怪的运行时异常.将"var"更改为"int"修复了运行时异常,但我不明白为什么.我把代码煮成了这个例子;

public class Program
{
    private static List<string> Test(string i) { return new List<string> {i}; }
    private static dynamic GetD() { return 1; }

    public static void Main()
    {
        int value1 = GetD();   // <-- int
        var result1 = Test("Value " + value1);
        // No problem, prints "Value 1", First() on List<string> works ok.
        Console.WriteLine(result1.First());

        var value2 = GetD();   // <-- var
        var result2 = Test("Value " + value2);
        // The below line gives RuntimeBinderException 
        // 'System.Collections.Generic.List<string>' does not contain a 
        // definition for 'First'
        Console.WriteLine(result2.First());
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以看到"var"的类型是动态的而不是int,但为什么该类型传播到并影响调用的返回值的行为Test()

编辑:也许我应该澄清我的问题; 我可以看到dynamic传播到result2,我无法理解的是为什么,当IDE清楚地表明这List<string> Test(string)是被调用的方法时,它仍然将返回值推断为动态.这是IDE比编译器更聪明的情况吗?

Céd*_*non 2

你的代码是这样编译的:

\n\n
public static void Main()\n{\n    int value1 = GetD();   // <-- int\n    List<string> result1 = Test("Value " + value1);\n    // No problem, prints "Value 1", First() on List<string> works ok.\n    Console.WriteLine(result1.First());\n\n    dynamic value2 = GetD();   // <-- var\n    dynamic result2 = Test("Value " + value2);\n    // The below line gives RuntimeBinderException \n    // \'System.Collections.Generic.List<string>\' does not contain a \n    // definition for \'First\'\n    Console.WriteLine(result2.First());\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

result2是一个动态对象,那么它不支持扩展方法(用作扩展方法)。

\n\n

但是,您可以这样做:

\n\n
Console.WriteLine(Enumerable.First(result2));\n
Run Code Online (Sandbox Code Playgroud)\n\n

更新

\n\n

你的 IDE 没那么聪明。尝试添加新方法:

\n\n
private static List<int> Test(int i) { return new List<int> { i }; }\n
Run Code Online (Sandbox Code Playgroud)\n\n

它会向您建议两种可能性。

\n\n

更新2

\n\n

C#规范第7.6.5段:

\n\n
\n

如果至少满足以下条件之一,则调用表达式会动态绑定 (\xc2\xa77.2.2):

\n\n
    \n
  • 主表达式具有编译时类型动态。
  • \n
  • 可选参数列表中的至少一个参数具有编译时类型动态,并且主表达式没有委托类型。
  • \n
\n
\n