C# Main方法 和顶级语句详解
总目录
前言
Main方法 和顶级语句 介绍。
一、Main方法
1. 基本信息
- Main 方法是 C# 应用程序的入口点。 Main 方法是应用程序启动后调用的第一个方法。
- C# 程序中只能有一个入口点。如果多个类包含 Main 方法,必须使用 StartupObject 编译器选项来编译程序,以指定将哪个 Main 方法用作入口点。具体操作如下图所示:
2. 最常见的 Main 声明
示例未指定访问修饰符,因此默认为隐式 private。 这是典型的,但可以指定任何显式访问修饰符。
static void Main() { }
static int Main() { }
static void Main(string[] args) { }
static int Main(string[] args) { }
static async Task Main() { }
static async Task<int> Main() { }
static async Task Main(string[] args) { }
static async Task<int> Main(string[] args) { }
- Main 方法是可执行程序的入口点,也是程序控制开始和结束的位置。
- Main 必须在类或结构中进行声明。 封闭 class 可以是 static。
- Main 必须为 static。
- Main 可以具有任何访问修饰符(file 除外)。
- Main 的返回类型可以是 void、int、Task 或 Task。
- 仅当 Main 返回 Task 或 Task<int> 时,Main 的声明可包括 async 修饰符。 这明确排除了 async void Main 方法。
- 使用或不使用包含命令行自变量的 string[] 参数声明 Main 方法都行。 使用 Visual Studio 创建 Windows 应用程序时,可以手动添加此形参,也可以使用 GetCommandLineArgs() 方法来获取命令行实参。 参数被读取为从零开始编制索引的命令行自变量。 与 C 和 C++ 不同,程序的名称不被视为 args 数组中的第一个命令行实参,但它是 GetCommandLineArgs() 方法中的第一个元素。
3. Main 返回值
- 可以通过以下方式之一定义方法,以从 Main 方法返回 int:
- 如果不使用 Main 的返回值,则返回 void 或 Task :
1)如何访问进程的退出代码。
返回 int 或 Task 可使程序将状态信息传递给调用可执行文件的其他程序或脚本。实现案例如下所示:
- 创建控制台应用程序。 修改 Program.cs 中的 Main 方法,如下所示:
internal class Program
{
static int Main()
{
//...
return 0;
}
}
注意:此处创建的控制台应用程序 是基于.NET 的,而非.NET Framework
在 Windows 中执行程序时,从 Main 函数返回的任何值都存储在环境变量中。 可使用批处理文件中的 ERRORLEVEL 或 PowerShell 中的 $LastExitCode 来检索此环境变量。
- 接下来,创建一个 PowerShell 脚本来运行应用程序并显示结果。
dotnet run
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
pause
将以上代码粘贴到文本文件中,并在包含该项目的文件夹中将其另存为 test.ps1。 可通过在 PowerShell 提示符下键入 test.ps1 来运行 PowerShell 脚本。
PowerShell 输出结果:
因为代码返回零,所以批处理文件将报告成功。 但是,如果将 Program.cs 更改为返回非零值,然后重新编译程序,则 PowerShell 脚本的后续执行将报告为失败。
4. Async Main 返回值
class AsyncMainReturnValTest
{
public static int Main()
{
return AsyncConsoleWork().GetAwaiter().GetResult();
}
private static async Task<int> AsyncConsoleWork()
{
// Main body here
return 0;
}
}
等效于:
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
// main body here
return 0;
}
}
5. 命令行参数
1)使用 string[] args 参数时
Main 方法的参数是一个表示命令行参数的 String 数组。 通常,通过测试 Length 属性来确定参数是否存在,例如:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
2)不使用string[] args 参数时
这种方式,可以简化代码。
如果需要获取命令行参数,可使用 Environment.CommandLine 或 Environment.GetCommandLineArgs 从控制台或 Windows 窗体应用程序的任意位置访问命令行参数。
using System;
class Sample
{
public static void Main()
{
Console.WriteLine();
// Invoke this sample with an arbitrary set of command line arguments.
string[] arguments = Environment.GetCommandLineArgs();
Console.WriteLine("GetCommandLineArgs: {0}", string.Join(", ", arguments));
}
}
/*
This example produces output like the following:
C:\>GetCommandLineArgs ARBITRARY TEXT
GetCommandLineArgs: GetCommandLineArgs, ARBITRARY, TEXT
*/
using System;
class Example
{
public static void Main()
{
Console.WriteLine();
// Invoke this sample with an arbitrary set of command line arguments.
Console.WriteLine("CommandLine: {0}", Environment.CommandLine);
}
}
// The example displays output like the following:
// C:\>env0 ARBITRARY TEXT
//
// CommandLine: env0 ARBITRARY TEXT
二、顶级语句
1. 基本信息
-
无需在控制台应用程序项目中显式包含 Main 方法。 可以使用顶级语句功能最大程度地减少必须编写的代码。
-
使用顶级语句可直接在文件的根目录中编写可执行代码,而无需在类或方法中包装代码。
- 这意味着无需使用 Program 类和 Main 方法即可创建程序。 在这种情况下,编译器将使用入口点方法为应用程序生成 Program 类。 生成方法的名称不是 Main,而是你的代码无法直接引用的实现详细信息。
下面是一个 Program.cs 文件看,它是 C# 10 中的一个完整 C# 程序:
Console.WriteLine("Hello World!");
2. 注意事项
- 仅能有一个顶级文件
- 没有其他入口点
- using 指令
- 如果包含 using 指令,这些指令必须先出现在文件中,如以下示例中所示:
using System.Text;
StringBuilder builder = new();
builder.AppendLine("The following arguments are passed:");
// Display the command line arguments using the args variable.
foreach (var arg in args)
{
builder.AppendLine($"Argument={arg}");
}
Console.WriteLine(builder.ToString());
// Return a success code.
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!");
}
}
}
结语
回到目录页: C# 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料:
官方 - C#文档
官方 - .NET 文档
C#、.NET Framework、CLR的关系