Main概述

  • Main 方法是 C# 应用程序的入口点。 (库和服务不要求使用 Main 方法作为入口点)。
  • 自 C# 9 起,可以省略 Main 方法,直接在顶级语句中操作
  • 如果多个类包含 Main 方法,必须使用 StartupObject 编译器选项来编译程序,以指定将哪个 Main 方法用作入口点。
class TestClass
{
    static void Main(string[] args)
    {
        // Display the number of command line arguments.
        Console.WriteLine(args.Length);
    }
}
  • Main 在类或结构中声明。 Main 必须是 static,public不必须
  • Main 的返回类型可以是 void、int、Task 或 Task。
  • 当且仅当 Main 返回 Task 或 Task 时,Main 的声明可包括 async 修饰符。
  • 使用或不使用包含命令行自变量的 string[] 参数声明 Main 方法都行。
public static void Main() { }
public static int Main() { }
public static void Main(string[] args) { }
public static int Main(string[] args) { }
public static async Task Main() { }
public static async Task<int> Main() { }
public static async Task Main(string[] args) { }
public static async Task<int> Main(string[] args) { }

Async Main 返回值

  • 声明 Main 的 async 返回值时,编译器会生成样本代码,用于调用 Main 中的异步方法。
  • 如果未指定 async 关键字,则需要自行编写该代码
  • 将 Main 声明为 async 的优点是,编译器始终生成正确的代码。
public static void Main()
{
    AsyncConsoleWork().GetAwaiter().GetResult();
}

private static async Task<int> AsyncConsoleWork()
{
    // Main body here
    return 0;
}

等效于
static async Task<int> Main(string[] args)
{
    return await AsyncConsoleWork();
}

当应用程序入口点返回 Task 或 Task 时,编译器生成一个新的入口点,该入口点调用应用程序代码中声明的入口点方法。
假设此入口点名为 $GeneratedMain,编译器将为这些入口点生成以下代码:

  • static Task Main() 导致编译器发出 private static void $GeneratedMain() => Main().GetAwaiter().GetResult(); 的等效项
  • static Task Main(string[]) 导致编译器发出 private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult(); 的等效项
  • static Task Main() 导致编译器发出 private static int $GeneratedMain() => Main().GetAwaiter().GetResult(); 的等效项
  • static Task Main(string[]) 导致编译器发出 private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult(); 的等效项

main参数

Main 方法的参数是一个表示命令行参数的 String 数组。 通常,通过测试 Length 属性来确定参数是否存在

if (args.Length == 0)
{
//args 数组不能为 null。 因此,无需进行 null 检查即可放心地访问 Length 属性。
    System.Console.WriteLine("Please enter a numeric argument.");
    return 1;
}

顶级语句

C# 9 开始,无需在控制台应用程序项目中显式包含 Main 方法。
下面是 C# 10 中的一个完整 C# 程序:

Console.WriteLine("Hello World!");

顶级语句规则

  • 一个项目只能有一个包含顶级语句的文件。
  • 可以显式编写 Main 方法,但它不能作为入口点。会被编译时忽略,并发出警告
  • 不能使用 -main 编译器选项来选择入口点,即使该项目具有一个或多个 Main 方法。
  • 如果包含 using 指令,则它们必须首先出现在文件中,如
using System.Text;

StringBuilder builder = new();
builder.AppendLine("Hello");
builder.AppendLine("World!");

Console.WriteLine(builder.ToString());

  • 顶级语句隐式位于全局命名空间中。
  • 具有顶级语句的文件还可以包含命名空间和类型定义,但它们必须位于顶级语句之后。
  • 顶级语句可以引用 args 变量来访问输入的任何命令行参数。
if (args.Length > 0)
{
    foreach (var arg in args)
    {
        Console.WriteLine($"Argument={arg}");
    }
}
else
{
    Console.WriteLine("No arguments");
}
  • 可以通过使用 await 来调用异步方法。
Console.Write("Hello ");
await Task.Delay(5000);
Console.WriteLine("World!");
  • 像在 Main 方法中返回 int 那样使用 return 语句。
  • 编译器会生成一个方法,作为具有顶级语句的项目的程序入口点。即隐式入口点 此方法的名称实际上并不是 Main,而是代码无法直接引用的实现细节。
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐