我們都知道,程序入口是Program的Main方法,在C# 9.0之前,我們需要顯示寫出這個Main方法,但是如果你使用VS2022新建一個控制台項目,你可能會發現Program里面的Main方法消失了,沒錯,這就是頂級語句。什么是頂級語句,我們可以正常的理解為Program中Main方法函數體的代碼,但是又不能完全這么理解,我們來看看頂級語句是什么,又做了那些限制?
什么是頂級語句?頂級語句其實是Main方法隱式的實現
頂級語句其實是隱式的生成Main方法,它會根據其中的代碼環境來生成Main方法的簽名,比如是否有await,是否有return等等:
return | await | Main方法簽名 |
存在 | 存在 | static async Task<int> 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