Main メソッドは、C# アプリケーションのエントリ ポイントです アプリケーションを起動すると、最初に Main メソッドが呼び出されます。
C# プログラムのエントリ ポイントは 1 つのみです。
Main メソッドを持つクラスが 2 つ以上ある場合、プログラムをコンパイルする際に StartupObject コンパイラ オプションを使用して、どの Main メソッドをエントリ ポイントとして使用するかを指定する必要があります。 詳細については、「StartupObject (C# コンパイラ オプション)」を参照してください。 次の例では、最初のアクションとしてコマンド ライン引数の数を表示します。
class TestClass
{
static void Main(string[] args)
{
Console.WriteLine(args.Length);
}
}
アプリケーションのエントリ ポイントとして、1 つのファイルで最上位レベルのステートメントを使用することもできます。
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 以降では、1 つのファイルにプログラムが含まれるファイル ベースのアプリをプログラムにすることができます。
ファイル ベースのアプリは、コマンド dotnet run <file.cs>を使用して実行するか、#!/usr/local/share/dotnet/dotnet run ディレクティブを最初の行として使用します (unix シェルのみ)。
概要
-
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() メソッドを使用して、コマンドライン引数を取得できます。 パラメーターは、インデックス 0 のコマンドライン引数として読み取られます。 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 関数からの戻り値はすべて 1 つの環境変数に格納されます。 この環境変数を取得するには、バッチ ファイルから ERRORLEVEL を使用するか、PowerShell から $LastExitCode を使用します。
dotnet CLI の dotnet build コマンドを使用してアプリケーションを構築できます。
次に、アプリケーションを実行して結果を表示する PowerShell スクリプトを作成します。 次のコードをテキスト ファイルに貼り付け、プロジェクトが保存されているフォルダーに test.ps1 として保存します。 PowerShell プロンプトに「test.ps1」と入力して PowerShell スクリプトを実行します。
コードから 0 が返されるため、バッチ ファイルは成功を報告します。 ただし、MainReturnValTest.csを変更して 0 以外の値を返し、プログラムを再コンパイルすると、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
非同期 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 フォーム アプリケーション内の任意の場所からコマンド ライン引数にアクセスすることもできます。 Windows フォーム アプリケーションの Main メソッド宣言でコマンド ライン引数を有効にするには、Main の宣言を手動で変更する必要があります。 Windows フォーム デザイナーが生成するコードで作成されるのは、入力パラメーターなしの 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);
詳細については、次のトピックを参照してください。 Parse および Convert
ヒント
コマンド ライン引数の解析は複雑になることがあります。 プロセスを簡単にするため、System.CommandLine ライブラリ (現在ベータ版) の使用を検討してください。
コンソール アプリケーションでコマンド ライン引数を使用する方法の例を次に示します。 アプリケーションは、実行時に引数を 1 つ受け取り、整数に変換し、その値の階乗を計算しています。 引数がない場合は、アプリケーションの正しい使用方法を説明するメッセージを表示します。
コマンド プロンプトからアプリケーションをコンパイルして実行するには、次の手順を実行します。
次のコードをテキスト エディターに貼り付け、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# の構文と使用法に関する信頼性のある情報源です。
関連項目
.NET