什么情况下生成的Top Level Statement类会是$Program?

2024-01-13

我一直假设顶级语句生成的类是一个隐藏的、不可访问的类。例如:

System.Console.WriteLine(2);

partial class Program
{
    public static string abc = "def";
}

当使用 SharpLab.io 运行时默认分支 https://sharplab.io/#v2:CYLg1APgAgjAdLAnACgEwEoDcBYAUHgBwEMAnAFwEsiAbAAilXpgHY8BvPWr+gZiYDYmABlpEARgGNaAXloAiYAFMAZnJy4AvkA= or the “C# 9:顶级语句(2020 年 5 月 27 日)”分支 https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLQGUCWBbADgGwgAUEB7AcwSm2QBoATEAagB8ABARgDpOBOACgBMASgDcAWABQU3FAQxMUfAAI2g1RwDsUgN5TlB1QGYNANg0AGZVGABjZQF5lAInoQwziZIC+QA==,生成的 C# 将是

// [ ... using and assembly attributes ... ]
internal static class $Program
{
    private static void $Main(string[] args)
    {
        Console.WriteLine(2);
    }
}
internal class Program
{
    public static string abc = "def";
}

Though it's interesting to note that the default branch emits <Program>$ not $Program and <Main>$ not $Main.

然而,它被称为 https://stackoverflow.com/a/71058076/1043380你可以使用partial class Program来扩充生成的类。修改代码以打印该字段...

System.Console.WriteLine(abc);
partial class Program { public static string abc = "def"; }

...并再次运行一些特别的较新的分支“C# 下一篇:文件类型(2022 年 7 月 5 日)” https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLRgJYBsKpgTwAcUAaAExAGoAfAAQEYA6BgTgAopgBjASgG4AsAChCUBDAxQsAAloAmWfQDs0gN6yAzIoBsigAzTOXaQF5pAIjIQw5vtIC+woA将生成组合类:

// [ ... using and assembly attributes ... ]
internal class Program
{
    public static string abc = "def";

    private static void <Main>$(string[] args)
    {
        Console.WriteLine(abc);
    }
}

For the record, I do not know what C# compiler version is used with this branch, I'm assuming some version of C# 10.

但是,那默认分支 https://sharplab.io/#v2:CYLg1APgAgjAdLAnACgIYCMDGBKA3AWACgAHVAJwBcBLVAGwAIoAmRmAdnoG9GBmVgNlYAGehkz0AvPQBEwAKYAzabnoBfIkA=== or “C# 9:顶级语句(2020 年 5 月 27 日)”分支 https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLQGUCWBbADgGwgAUEB7AcwSm2QBoATEAagB8ABARgDpOBOACijAAxgEoA3AFgAULigIYmKPgAEbAExqOAdhUBvNQGYtANi0AGFUOEqAvCoBE9CGAfiVAXxlA=将产生语法错误,其中abc找不到字段。

我在 Sharplab 之外重现此问题时遇到问题。创建.Net 5 / C# 9(此功能的版本出来了 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/top-level-statements) 控制台应用程序在本地编译并运行:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType> <TargetFramework>net5.0</TargetFramework> <LangVersion>9.0</LangVersion>
  </PropertyGroup>
</Project>
System.Console.WriteLine(abc);
partial class Program { public static string abc = "def"; }
// I have SDK 5.0.408 and runtime 5.0.14,15,17 installed, along with others for core 3.1 and .net 6

点网小提琴 https://dotnetfiddle.net/nFKPbM也会编译代码,但它只允许我选择.Net 6,C#版本未知。

假设这不是 Sharplabs 的错误,我的假设是发出的类针对不同的 C# 9 编译器发生了变化。 Sharplabs 可能会展示原本的C# 9 编译器,但我的计算机可能正在运行较新的版本。

我能看到的唯一其他证据是对dotnet/csharplang git 存储库 https://github.com/dotnet/csharplang/commit/d7c3bef81a34aaa417cd47675fdd2e73ef092d27#diff-a18fd8818ea93281948d26740ec76d542595a3bc52c075075937d8a12c175013L150-R152改变了记录的发出类static class $Program to partial class Program。尽管该文件位于“proposal”文件夹中,但它似乎与“proposal”文件夹中的文件相同。发布到微软的文档 https://web.archive.org/web/20220411230010/https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/top-level-statements,所以在过去的某个时刻,有记录表明类名是$Program.

为什么 Sharplab 将第一个代码块编译为两个类,为什么它不能接受部分类来扩充入口点类?这个功能发布后有修改吗?


这现在反映在顶级声明 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/top-level-statements#semantics功能规格:

该类型被命名为“Program”,因此可以通过源代码中的名称进行引用。它是一个部分类型,因此源代码中名为“Program”的类型也必须声明为部分类型。

这是从previous https://github.com/dotnet/csharplang/blob/1dbcfb485ce782bb4cb6e7bbbdeb264bcb9641b7/proposals/csharp-9.0/top-level-statements.md via 这次提交 https://github.com/dotnet/csharplang/commit/d7c3bef81a34aaa417cd47675fdd2e73ef092d272022 年 6 月 22 日:

请注意,名称“Program”和“Main”仅用于说明目的,编译器使用的实际名称取决于实现,并且类型和方法都不能通过源代码中的名称引用.

我猜这个改变是为了支持ASP.NET Core 中的集成测试 https://learn.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#aspnet-core-6-9.NET 6 中的新托管模型以及首次提及这种可能性的日期2021 年 10 月 21 日 https://github.com/dotnet/AspNetCore.Docs/blob/aafdca64fc73938c1b9878018e77d6ecca91bcce/aspnetcore/migration/50-to-60-samples.md#project-file-csproj.

简而言之 - 任何现代 .NET 6+ 编译器都应该生成Program类,对于早期版本,您不应该依赖命名(尽管 .NET 5 现在已经 EOL,这不是很相关)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么情况下生成的Top Level Statement类会是$Program? 的相关文章

随机推荐