顶级语句 - 不使用
对新应用使用 顶级语句 。 通过使用顶级语句,可以直接在文件的根目录中编写可执行代码。
下面是一个 Program.cs 文件,该文件是完整的 C# 程序:
Console.WriteLine("Hello World!");
创建一个新的控制台应用程序时使用 dotnet new console,它默认使用顶级语句。 它们适用于任何大小的程序-从小型实用工具和 Azure Functions 到完整应用程序。 如果有使用显式 Main 方法的现有应用程序,则无需对其进行转换。 这两种样式都编译为等效代码。
以下各节介绍了关于顶级语句可执行与不可执行操作的规则。
入口点规则
一个应用程序只能有一个入口点。 项目只能有一个具有顶级语句的文件,但它可以有任意数量的没有顶级语句的源代码文件。 可以显式编写方法 Main ,但它不能用作入口点。 在具有顶级语句的项目中,即使项目具有一个或多个-main方法,也不能使用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# 14 开始,程序可以是 基于文件的应用,其中单个文件包含该程序。 使用命令运行dotnet <file.cs>,或者直接在 Unix 上使用文件名(例如,./file.cs)。 后者需要在第一行中包含 #!/usr/bin/env dotnet 指令,并设置执行权限(chmod +x <file>)。
using 指令
对于包含顶级语句的单个文件, using 指令必须首先出现在该文件中,如以下示例所示:
using System.Text;
StringBuilder builder = new();
builder.AppendLine("The following arguments are passed:");
foreach (var arg in args)
{
builder.AppendLine($"Argument={arg}");
}
Console.WriteLine(builder.ToString());
return 0;
命名空间和类型定义
顶级语句隐式位于全局命名空间中。 具有顶级语句的文件还可以包含命名空间和类型定义,但它们必须位于顶级语句之后。 例如:
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 来执行异步方法。 当顶级代码包含 await 时,编译器将生成一个 Task 入口点。 运行时监视Task的完成情况,使进程保持运行中,直到所有异步工作完成。 例如:
Console.Write("Hello ");
await Task.Delay(5000);
Console.WriteLine("World!");
若要在应用程序结束时返回退出代码,请使用 return 该语句。 编译器生成一个入口点,当代码同时包含 Task<int> 和 await 时,该入口点返回 return,或当代码仅包含 int 时返回 return。 例如:
string? s = Console.ReadLine();
int returnValue = int.Parse(s ?? "-1");
return returnValue;