內容復制自:https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/top-level-statements
先決條件
需要將計算機設置為運行 .NET 6,其中包括 C# 10 編譯器。 自 Visual Studio 2022 或 .NET 6 SDK 起,開始提供 C# 10 編譯器。
本教程假設你熟悉 C# 和 .NET,包括 Visual Studio 或 .NET CLI。
開始探索
借助頂級語句,你可以將程序的入口點置於類的靜態方法中,以避免額外的工作。 新控制台應用程序的典型起點類似於以下代碼:
using System; namespace Application { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } }
上面的代碼是運行 dotnet new console
命令並創建新控制台應用程序的結果。 這 11 行只包含一行可執行代碼。
可以通過新的頂級語句功能簡化該程序。 由此,你可以刪除此程序中除兩行以外的所有行:
// See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!");
備注
重要 適用於 .NET 6 的 C# 模板使用頂級語句。 如果你已升級到 .NET 6 預覽版,則應用程序可能與本文中的代碼不匹配。 有關詳細信息,請參閱有關新 C# 模板生成頂級語句的文章 .NET 6 SDK 還為使用以下 SDK 的項目添加了一組隱式 指令: Microsoft.NET.Sdk Microsoft.NET.Sdk.Web Microsoft.NET.Sdk.Worker 這些隱式 global using 指令包含項目類型最常見的命名空間。
此功能簡化了開始探索新想法所需的操作。 你可以將頂級語句用於腳本編寫場景,或用於探索。
掌握基礎知識后,便可以開始重構代碼,並為生成的可重用組件創建方法、類或其他程序集。 頂級語句支持快速試驗和初學者教程。 它們還提供一條從試驗到完整程序的平滑路徑。
頂級語句按照其在文件中出現的順序執行。 頂級語句只能用在應用程序的一個源文件中。 如果將其用於多個文件,編譯器將生成錯誤。
摘要
使用頂級語句,可以更輕松地創建簡單的程序來探索新的算法。 可以嘗試使用不同的代碼片段來試驗算法。 了解了哪些可用后,可以重構代碼,使其更易於維護。
頂級語句可簡化基於控制台應用程序的程序。 其中包括 Azure Functions、GitHub 操作和其他小實用工具。 有關詳細信息,請參閱頂級語句(C# 編程指南)。
--------------------------------------------------------
內容來源:https://docs.microsoft.com/zh-cn/dotnet/csharp/fundamentals/program-structure/top-level-statements
頂級語句 - 不使用 Main
方法的程序
從 C# 9 開始,無需在控制台應用程序項目中顯式包含 Main
方法。 相反,可以使用頂級語句功能最大程度地減少必須編寫的代碼。 在這種情況下,編譯器將為應用程序生成類和 Main
方法入口點。
下面是一個 Program.cs 文件看,它是 C# 10 中的一個完整 C# 程序:
Console.WriteLine("Hello World!");
借助頂級語句,可以為小實用程序(如 Azure Functions 和 GitHub Actions)編寫簡單的程序。 它們還使初次接觸 C# 的程序員能夠更輕松地開始學習和編寫代碼。
以下各節介紹了可對頂級語句執行和不能執行的操作的規則。
僅能有一個頂級文件
一個應用程序只能有一個入口點。 一個項目只能有一個包含頂級語句的文件。 在項目中的多個文件中放置頂級語句會導致以下編譯器錯誤:
CS8802:只有一個編譯單元可具有頂級語句。
一個項目可具有任意數量的其他源代碼文件,這些文件不包含頂級語句。
沒有其他入口點
可以顯式編寫 Main
方法,但它不能作為入口點。 編譯器將發出以下警告:
CS7022:程序的入口點是全局代碼;忽略“Main()”入口點。
在具有頂級語句的項目中,不能使用 -main 編譯器選項來選擇入口點,即使該項目具有一個或多個 方法。
using
指令
如果包含 using 指令,則它們必須首先出現在文件中,如以下示例中所示:
using System.Text; StringBuilder builder = new(); builder.AppendLine("Hello"); builder.AppendLine("World!"); Console.WriteLine(builder.ToString());
全局命名空間
頂級語句隱式位於全局命名空間中。
命名空間和類型定義
具有頂級語句的文件還可以包含命名空間和類型定義,但它們必須位於頂級語句之后。 例如:
MyClass.TestMethod(); MyNamespace.MyClass.MyMethod(); public class MyClass { public static void TestMethod() { Console.WriteLine("Hello World!"); } } namespace MyNamespace { class MyClass { public static void MyMethod() { Console.WriteLine("Hello World from MyNamespace.MyClass.MyMethod!"); } } }
args
頂級語句可以引用 args
變量來訪問輸入的任何命令行參數。 args
變量永遠不會為 null,但如果未提供任何命令行參數,則其 Length
將為零。 例如:
if (args.Length > 0) { foreach (var arg in args) { Console.WriteLine($"Argument={arg}"); } } else { Console.WriteLine("No arguments"); }
await
可以通過使用 await
來調用異步方法。 例如:
Console.Write("Hello "); await Task.Delay(5000); Console.WriteLine("World!");
進程的退出代碼
若要在應用程序結束時返回 int
值,請像在 Main
方法中返回 int
那樣使用 return
語句。 例如:
string? s = Console.ReadLine(); int returnValue = int.Parse(s ?? "-1"); return returnValue;
隱式入口點方法
編譯器會生成一個方法,作為具有頂級語句的項目的程序入口點。 此方法的名稱實際上並不是 Main
,而是代碼無法直接引用的實現細節。
方法的簽名取決於頂級語句是包含 await
關鍵字還是 return
語句。 下表顯示了方法簽名的外觀,為了方便起見,在表中使用了方法名稱 Main
。
頂級代碼包含 | 隱式 Main 簽名 |
---|---|
await 和 return |
static async Task<int> Main(string[] args) |
await |
static async Task Main(string[] args) |
return |
static int Main(string[] args) |
否 await 或 return |
static void Main(string[] args) |
C# 語言規范
有關詳細信息,請參閱 C# 語言規范。 該語言規范是 C# 語法和用法的權威資料。
個人建議:
建議去閱讀功能規范:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/top-level-statements
微軟官網給的設計該功能的動機
There's a certain amount of boilerplate surrounding even the simplest of programs, because of the need for an explicit Main
method. This seems to get in the way of language learning and program clarity. The primary goal of the feature therefore is to allow C# programs without unnecessary boilerplate around them, for the sake of learners and the clarity of code.
由於需要顯式的Main方法,即使是最簡單的程序也有一定數量的樣板文件。這似乎妨礙了語言學習和程序清晰度。因此,這個特性的主要目的是為了讓c#程序沒有不必要的樣板,既有利於學習者,又便於代碼的清晰。