为什么编译器应该返回特定类型时却返回“dynamic”?

the*_*ist 2 c# .net-framework-version visual-studio-2022

下面是我正在运行的确切代码。为什么编译器返回dynamic而不输入MyClass

我的项目在 .NET Framework 4.7.2 上运行,但我通过添加public static class IsExternalInit { }和将其配置为使用最新的 C#

<PropertyGroup>
    <LangVersion>latest</LangVersion>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

我的代码:

internal class Program
{
    class MyClass
    {
    }

    static class MyParser
    {
        public static MyClass Parse(dynamic data)
        {
            return new MyClass();
        }
    }

    static void Do(dynamic data)
    {
        var parsedObj = MyParser.Parse(data);
        ...
    }

    static void Main(string[] args)
    {
        Do(JsonConvert.DeserializeObject(""));
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Eri*_*ert 8

\n

为什么编译器dynamic应该返回特定类型时却返回?

\n
\n

这个问题预设了一个谎言。编译器的行为是正确的,因此询问为什么它应该做不正确的事情使得很难回答您的问题。

\n

相反,我将回答“规范的哪一部分确定编译器何时应将调用分类为动态调用?”的问题。

\n
\n

我建议您参阅规范的第 11.7.8.1 节,其中规定:

\n

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11781-general

\n
\n

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

\n
    \n
  • Primary_Expression 具有编译时类型动态。
  • \n
  • 可选参数列表中至少有一个参数具有编译时类型动态。
  • \n
\n

在这种情况下,编译器将 invoking_expression 分类为\n动态类型的值。

\n
\n

data是“至少一个参数”,其类型为dynamic,所以就这样了。

\n

在您的特定情况下,适用有关附加错误检查的部分 - 但此部分不会影响调用类型的分类。

\n

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#1165-compile-time-checking-of-dynamic-member-inspiration

\n
\n

如果您的“为什么”问题没有通过参考规范得到回答,那么我鼓励您将其重新表述为“什么”问题。 很难知道“为什么”问题何时得到了满意的回答。

\n

  • @RandRandom:设计原则是:“动态”关闭编译时类型检查器,**当你关闭它时,它就关闭了**。如果您不想关闭编译时类型检查器,请不要使用动态! (3认同)
  • “动态”关闭编译时类型检查器并用运行时绑定替换它。如果您有多个带有不同参数的“Parse()”方法,则该方法的每次执行都可能调用不同的函数,并具有不同的返回类型。因此,为什么返回变量的类型是“dynamic”。编译器不会尝试猜测运行时绑定将做什么。 (3认同)
  • @RandRandom:我想也许你错误地解析了这个句子。它是“可选(参数列表)”,而不是“(可选参数)列表”。也就是说,参数列表是可选的。它不是指“可选参数列表”。 (2认同)