gun*_*171 7 c# c#-9.0 toplevel-statement
我一直假设顶级语句生成的类是一个隐藏的、不可访问的类。例如:
System.Console.WriteLine(2);
partial class Program
{
public static string abc = "def";
}
Run Code Online (Sandbox Code Playgroud)
当使用默认分支或“C# 9:顶级语句(2020 年 5 月 27 日)”分支在 SharpLab.io 中运行时,生成的 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";
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,默认分支发出<Program>$not$Program和<Main>$not $Main。
但是,众所周知,您可以使用partial类Program来增强生成的类。修改代码以打印该字段...
System.Console.WriteLine(abc);
partial class Program { public static string abc = "def"; }
Run Code Online (Sandbox Code Playgroud)
...并使用某些特定的较新分支“C# Next:文件类型(2022 年 7 月 5 日)”再次运行将生成组合类:
// [ ... using and assembly attributes ... ]
internal class Program
{
public static string abc = "def";
private static void <Main>$(string[] args)
{
Console.WriteLine(abc);
}
}
Run Code Online (Sandbox Code Playgroud)
根据记录,我不知道此分支使用什么 C# 编译器版本,我假设是 C# 10 的某个版本。
但是,默认分支或“C# 9:顶级语句(2020 年 5 月 27 日)”分支将产生语法错误,abc无法找到该字段。
我在 Sharplab 之外重现此问题时遇到问题。创建 .NET 5 / C# 9(此功能出现的版本)控制台应用程序在本地编译并运行:
System.Console.WriteLine(2);
partial class Program
{
public static string abc = "def";
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Dotnet fiddle也会编译代码,但它只允许我选择.NET 6,C#版本未知。
假设这不是 Sharplabs 的错误,我的假设是发出的类针对不同的 C# 9 编译器发生了变化。Sharplabs 可能会显示原始的C# 9 编译器,但我的计算机可能正在运行较新的版本。
我能看到的唯一其他证据是dotnet/csharplang git 存储库中的编辑,它将记录的发出类从 更改static class $Program为partial class Program。尽管此文件位于“proposal”文件夹中,但它似乎与发布到 Microsoft 文档中的文件相同,因此在过去的某个时刻,记录了该类名称为$Program.
为什么 Sharplab 将第一个代码块编译为两个类,为什么它不能接受部分类来扩充入口点类?这个功能发布后有修改吗?
这现在反映在顶级语句功能规范中:
该类型被命名为“Program”,因此可以通过源代码中的名称进行引用。它是一个部分类型,因此源代码中名为“Program”的类型也必须声明为部分类型。
通过2022 年 6 月 22 日的提交对之前的内容进行了更改:
请注意,名称“Program”和“Main”仅用于说明目的,编译器使用的实际名称取决于实现,并且类型和方法都不能通过源代码中的名称引用。
我的猜测是,所做的更改是为了支持ASP.NET Core与 .NET 6 中新托管模型的集成测试,并且首次提及这种可能性的日期是2021 年 10 月 21 日。
简而言之,任何现代 .NET 6+ 编译器都应该生成Program类,对于早期版本,您不应该依赖命名(尽管 .NET 5 现在已经 EOL,这不是很相关)。