我们都知道,程序入口是Program的Main方法,在C# 9.0之前,我们需要显示写出这个Main方法,但是如果你使用VS2022新建一个控制台项目,你可能会发现Program里面的Main方法消失了,没错,这就是顶级语句。什么是顶级语句,我们可以正常的理解为Program中Main方法函数体的代码,但是又不能完全这么理解,我们来看看顶级语句是什么,又做了那些限制?
什么是顶级语句?顶级语句其实是Main方法隐式的实现
顶级语句其实是隐式的生成Main方法,它会根据其中的代码环境来生成Main方法的签名,比如是否有await,是否有return等等:
return | await | Main方法签名 |
存在 | 存在 | static async Task Main(string[] args) |
存在 | 不存在 | static int Main(string[] args) |
不存在 | 存在 | static async Task Main(string[] args) |
不存在 | 不存在 | static void Main(string[] args) |
这样,我们可以根据我们自己的需要时使用await和return,而不需要关系Main方法的签名了。
此外,在顶级语句的环境中,我们有一个特殊的变量可以直接使用,那就是args,顾名思义,它其实就是Main方法中的args参数,命令行传入的这个args参数永不会为null,无参数是一个空的数组,除非手动的给args赋值为null,这点与Main方法是一致的。
顶级语句的一些限制
1、使用顶级语句的项目必须是可执行的项目
这个很好理解,顶级语句其实是Main方法隐式的实现,项目启动默认会将它作为入口,那么一个非可执行项目中的顶级语句是没有任何意义的。
2、一个项目只能存在一个顶级文件
默认的情况,如果顶级文件存在,那么其它显示定义的Main方法都将不会作为程序运行的入口,而顶级语句其实是Main方法隐式的实现,那么一个项目中存在多个顶级文件,那么哪个作为入口呢?
注:个人觉得这点以后可能会被打破,因为像java等一些语言是允许多个入口的,只是在运行时可以配置指定使用哪个入口,而且我们的程序也是可以存在多个Main方法的,运行时可以通过-main指定,所以在不远的将来,或许会允许一个项目中存在多个顶级文件
3、顶级文件中如果使用using,那么using必须在顶级文件的最开头
using System.Linq; using System.Collections.Generic; var list = new List<int>() { 1, 2, 3 }; Console.WriteLine(list.Contains(1));
4、命名空间和类型定义
顶级文件中允许什么自定义类型和命名空间,但是要求自定义的类型和命名空间位于顶级文件的底部:
using System.Linq; using System.Collections.Generic; var list = new List<int>() { 1, 2, 3 }; Console.WriteLine(list.Contains(1)); public class Demo1 { } namespace MyNameSpace { class Demo1 { } }
顶级文件中定义的类,其实就是普通类,跟把它们放到单独的文件中是一样的
5、顶级文件中不允许存在公共方法
这就是说,顶级文件中生成Program只有一个Main方法,但是庆幸的是,顶级文件中允许存在本地方法,所以不用担心定义文件中代码混乱的问题了。
using System.Linq; using System.Collections.Generic; StaticMethod(); NonStaticMethod(); //非静态方法 void NonStaticMethod() { var list = new List<int>() { 1, 2, 3 }; Console.WriteLine(list.Contains(1)); } //静态方法 static void StaticMethod() { var list = new List<int>() { 1, 2, 3 }; Console.WriteLine(list.Contains(1)); }
总结
顶级语句就是一个语法糖,作用不大,但是新颖!
参考文档:
https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements