Main 方法是 C# 應用程式的進入點。 啟動應用程式時,Main 方法是第一個叫用的方法。
C# 程式中只能有一個進入點。 如果您具有多個含 Main 方法的類別,就必須使用 StartupObject 編譯器選項來編譯您的程式,以指定要使用哪一個 Main 方法做為進入點。 如需詳細資訊,請參閱 StartupObject (C# 編譯器選項)。 下列範例會顯示命令行自變數的數目做為其第一個動作:
class TestClass
{
static void Main(string[] args)
{
Console.WriteLine(args.Length);
}
}
您也可以在一個檔案中使用最上層語句作為應用程式的進入點。 就像 Main 方法一樣,最上層陳述式也可以傳回值以及存取命令列引數。 如需詳細資訊,請參閱最上層陳述式。 下列範例會使用 foreach 循環來顯示使用 args 變數的命令行自變數,而程式結尾會傳回成功程序代碼 (0):
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;
從 C# 14 開始,程式可以是 檔案型應用程式,其中單一檔案包含程式。 您可以使用命令 dotnet run <file.cs>執行檔案型應用程式,或使用#!/usr/local/share/dotnet/dotnet run指令作為第一行 (僅限 Unix Shell)。
概觀
- 方法是
Main可執行程式的進入點;它是程式控制開始和結束的位置。 -
Main必須在類別或結構內宣告。 封閉的class可以是static。 -
Main必須是static。 -
Main可以有任何存取權限修改子 (file除外)。 -
Main可以具有void、int、Task或Task<int>傳回型別。 - 唯有
Main傳回Task或Task<int>時,Main的宣告才能包含async修飾詞。 此規則特別排除方法async void Main。 -
Main方法不一定要使用包含命令列引數的string[]參數來宣告。 使用 Visual Studio 來建立 Windows 應用程式時,您可以手動新增參數,或使用 GetCommandLineArgs() 方法來取得命令列引數。 參數會讀入來做為以零為基礎的命令列引數。 與 C 和 C++ 不同,程式的名稱不會作為陣列中的args第一個命令列參數,但它是GetCommandLineArgs() 方法的第一個元素。
下列清單顯示最常見的 Main 宣告:
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) { }
前面的範例未指定存取修飾詞,因此預設情況下它們會隱含為 private。 您可以指定任何明確的存取修飾詞。
提示
當主控台應用程式必須啟動且等待 async 中的 Task 非同步作業時,新增的 Task<int> 與 await、Main 傳回型別可簡化程式碼。
Main() 傳回值
您可以使用下列其中一種方式,透過定義方法從 int 方法傳回 Main:
Main 宣告 |
Main 方法程式碼 |
|---|---|
static int Main() |
不使用 args 或 await |
static int Main(string[] args) |
使用args但不使用await |
static async Task<int> Main() |
使用await但不使用args |
static async Task<int> Main(string[] args) |
使用 args 和 await |
如果未使用來自Main的傳回值,那麼傳回void或Task可以使代碼稍微簡單一些。
Main 宣告 |
Main 方法程式碼 |
|---|---|
static void Main() |
不使用 args 或 await |
static void Main(string[] args) |
使用args但不使用await |
static async Task Main() |
使用await但不使用args |
static async Task Main(string[] args) |
使用 args 和 await |
不過,若是傳回 int 或 Task<int>,可讓程式將狀態資訊傳達給其他會叫用可執行檔的程式或指令碼。
下列範例示範如何存取流程的結束程式碼。
此範例使用 .NET Core 命令列工具。 如果您不熟悉 .NET Core 命令行工具,您可以在此 入門文章中了解它們。
執行 dotnet new console 來建立新的應用程式。 修改 Main 中的 方法,如下所示:
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
請記得將此應用程式儲存為 MainReturnValTest.cs。
在 Windows 中執行程式時,任何從 Main 函式傳回的值,皆會儲存在環境變數中。 您可以從批次檔使用 ERRORLEVEL 或從 PowerShell 使用 $LastExitCode 來擷取此環境變數。
您可以使用 dotnet CLIdotnet build 命令來建置應用程式。
接下來,建立 PowerShell 指令碼以執行此應用程式,並顯示結果。 將下列程式碼貼入文字檔,將它儲存為 test.ps1,並放到包含專案的資料夾中。 在 PowerShell 命令提示字元中鍵入 test.ps1,以執行 PowerShell 指令碼。
因為程式代碼傳回零,批處理檔會報告成功。 不過,如果您更改 MainReturnValTest.cs 的回傳值為非零,然後重新編譯程式,後續執行的 PowerShell 腳本將會報告失敗。
dotnet run
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
Execution succeeded
Return value = 0
「Async Main」傳回值
當您為 async 宣告 Main 的傳回值時,編譯程式會在 Main 中產生用於呼叫異步方法的樣板程式碼:
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
return 0;
}
}
在這兩個範例中,程序的主體都在 AsyncConsoleWork() 方法的主體內。
宣告 Main 成為 async 的優點是編譯器一律會產生正確的程式碼。
當應用程式進入點傳回 Task 或 Task<int> 時,編譯器會產生新的進入點,以呼叫應用程式程式碼中宣告的進入點方法。 假設此進入點稱為 $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<int> Main()會導致編譯器發出private static int $GeneratedMain() => Main().GetAwaiter().GetResult();的對等項目 -
static Task<int> Main(string[])會導致編譯器發出private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();的對等項目
注意
如果這些範例在 async 方法上使用 Main 修飾詞,編譯器會產生相同的程式碼。
命令列引數
您可以使用下列其中一種方式,透過定義方法以將引數傳送給 Main 方法:
Main 宣告 |
Main 方法程式碼 |
|---|---|
static void Main(string[] args) |
沒有傳回值或 await |
static int Main(string[] args) |
傳回值,但未使用 await |
static async Task Main(string[] args) |
使用 await 但不會傳回值 |
static async Task<int> Main(string[] args) |
傳回值並使用 await |
如果未使用這些參數,您可以從方法宣告中省略 args,使代碼稍微簡單一點:
Main 宣告 |
Main 方法程式碼 |
|---|---|
static void Main() |
沒有傳回值或 await |
static int Main() |
傳回值,但未使用 await |
static async Task Main() |
使用 await 但不會傳回值 |
static async Task<int> Main() |
傳回值並使用 await |
注意
您也可以使用 Environment.CommandLine 或 Environment.GetCommandLineArgs,以從主控台或 Windows Forms 應用程式的任何點存取命令列引數。 若要在 Windows Forms 應用程式的 Main 方法宣告中啟用命令列引數,您必須手動修改 Main 的宣告。 Windows Forms 設計工具所產生的程式碼會建立沒有輸入參數的 Main。
Main 方法的參數是代表命令列引數的 String 陣列。 您通常會透過測試 Length 屬性來決定引數是否存在,例如:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
提示
args 陣列不可為 Null。 因此,在沒有 Null 檢查的情況下存取 Length 屬性是安全的。
您也可以使用 Convert 類別或 Parse 方法,將字串引數轉換為數字類型。 例如,下列陳述式將使用 string 方法,以將 long 轉換為 Parse 數字:
long num = Int64.Parse(args[0]);
您也可以使用 C# 類型 long,其別名為 Int64:
long num = long.Parse(args[0]);
您還可以使用 Convert 類別方法 ToInt64 執行相同作業:
long num = Convert.ToInt64(s);
提示
剖析命令列引數可能很複雜。 請考慮使用 System.CommandLine 程式庫 (目前為 beta 版) 來簡化處理程序。
下列範例示範如何在主控台應用程式中使用命令列引數。 應用程式會在執行階段接受一個引數,並將引數轉換為整數,以及計算數字的階乘。 如果未提供任何引數,則應用程式會發出說明程式正確用法的訊息。
若要從命令提示字元編譯和執行應用程式,請遵循下列步驟︰
將下列程式碼貼入任何文字編輯器,然後將檔案儲存為名稱為 Factorial.cs 的文字檔案。
public class Functions { public static long Factorial(int n) { // Test for invalid input. if ((n < 0) || (n > 20)) { return -1; } // Calculate the factorial iteratively rather than recursively. long tempResult = 1; for (int i = 1; i <= n; i++) { tempResult *= i; } return tempResult; } } class MainClass { static int Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Please enter a numeric argument."); Console.WriteLine("Usage: Factorial <num>"); return 1; } int num; bool test = int.TryParse(args[0], out num); if (!test) { Console.WriteLine("Please enter a numeric argument."); Console.WriteLine("Usage: Factorial <num>"); return 1; } long result = Functions.Factorial(num); if (result == -1) Console.WriteLine("Input must be >= 0 and <= 20."); else Console.WriteLine($"The Factorial of {num} is {result}."); return 0; } }在
Main方法的開頭,程式會檢查是否未提供輸入參數,將args參數的長度與0比較,若未找到任何參數則顯示說明。
如果提供自變數 (args.Length大於 0),程式會嘗試將輸入自變數轉換成數位。 如果自變數不是數字,這個範例會擲回例外狀況。
階乘計算完成後(結果儲存在result類型的long變數中),會根據result變數列印詳細結果。從 [開始] 畫面或 [開始] 功能表中,開啟 Visual Studio [開發人員命令提示字元] 視窗,然後瀏覽至剛剛建立的檔案包含在內的資料夾。
若要編譯應用程式,請輸入下列命令:
dotnet build如果您的應用程式沒有編譯錯誤,則會建立名為 Factorial.dll的 二進位檔。
輸入下列命令以計算 3 的階乘:
dotnet run -- 3如果在命令行上輸入 3 做為程式的自變數,輸出會讀取:
The factorial of 3 is 6.
注意
在 Visual Studio 中執行應用程式時,您可以在專案設計工具、偵錯頁中指定命令列引數。
C# 語言規格
如需詳細資訊,請參閱<C# 語言規格>。 語言規格是 C# 語法及用法的限定來源。