Main() とコマンド ライン引数
Main
メソッドは、C# アプリケーションのエントリ ポイントです (ライブラリおよびサービスでは、エントリ ポイントとしての Main
メソッドは必要ありません)。アプリケーションを起動すると、最初に Main
メソッドが呼び出されます。
C# プログラムのエントリ ポイントは 1 つのみです。 Main
メソッドを持つクラスが 2 つ以上ある場合、プログラムをコンパイルする際に StartupObject コンパイラ オプションを使用して、どの Main
メソッドをエントリ ポイントとして使用するかを指定する必要があります。 詳細については、「StartupObject (C# コンパイラ オプション)」を参照してください。
class TestClass
{
static void Main(string[] args)
{
// Display the number of command line arguments.
Console.WriteLine(args.Length);
}
}
C# 9 以降では、次の例のように Main
メソッドを省略し、Main
メソッド内にあるかのように C# ステートメントを記述することができます。
using System.Text;
StringBuilder builder = new();
builder.AppendLine("Hello");
builder.AppendLine("World!");
Console.WriteLine(builder.ToString());
暗黙的なエントリ ポイント メソッドを使用してアプリケーション コードを記述する方法の詳細については、「最上位レベルのステートメント」を参照してください。
概要
Main
メソッドは実行可能プログラムのエントリ ポイントであり、ここでプログラムの制御を開始および終了します。Main
は、クラスまたは構造体の内部で宣言されます。Main
はstatic
とする必要がありますが、public
である必要はありません。 (先ほどの例では、既定のprivate
のアクセスを受け取ります)。外側のクラスまたは構造体は、static である必要はありません。Main
の戻り値は、void
、int
、Task
、Task<int>
のいずれかになります。Main
でTask
またはTask<int>
が返される場合に限り、Main
の宣言にasync
修飾子を含めることができます。 これにより、async void Main
メソッドが明確に除外されます。Main
メソッドを宣言する際、コマンドライン引数を含むstring[]
パラメーターは指定してもしなくてもかまいません。 Visual Studio を使用して Windows アプリケーションを作成する場合、このパラメーターを手動で追加するか GetCommandLineArgs() メソッドを使用して、コマンドライン引数を取得できます。 パラメーターは、インデックス 0 のコマンドライン引数として読み取られます。 C や C++ とは異なり、プログラムの名前は、GetCommandLineArgs() の最初の要素です。args
配列の最初のコマンドライン引数として扱われることはありません。
有効な 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) { }
前の例ではすべて、public
アクセサー修飾子を使用しています。 これは一般的ですが、必須ではありません。
コンソール アプリケーションの Main
で await
を使用して非同期操作を開始する必要がある場合、戻り値の型 async
、Task
、Task<int>
を追加することでプログラム コードを簡略化できます。
Main() の戻り値
次のいずれかの方法でメソッドを定義することで、Main
メソッドから int
を返すことができます。
Main メソッド コード |
Main シグネチャ |
---|---|
args と await は使用しない |
static int Main() |
args を使用し、await を使用しない |
static int Main(string[] args) |
args を使用せず、await を使用する |
static async Task<int> Main() |
args と await を使用する |
static async Task<int> Main(string[] args) |
Main
からの戻り値を使用しない場合、void
か Task
を返すと少し簡単なコードにすることができます。
Main メソッド コード |
Main シグネチャ |
---|---|
args と await は使用しない |
static void Main() |
args を使用し、await を使用しない |
static void Main(string[] args) |
args を使用せず、await を使用する |
static async Task Main() |
args と await を使用する |
static async Task Main(string[] args) |
ただし、int
か Task<int>
を返すことによって、プログラムが状態の情報を、実行可能ファイルを呼び出す他のプログラムまたはスクリプトに伝達することができます。
次の例からは、プロセスの終了コードにアクセスする方法がわかります。
この例では、.NET Core コマンドライン ツールを使用します。 .NET Core コマンドライン ツールに慣れていない場合は、この概要の記事を参照してください。
dotnet new console
を実行して新しいアプリケーションを作成します。 program.cs の Main
メソッドを次のように変更します。
// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
プログラムを Windows で実行する場合、Main
関数からの戻り値はすべて 1 つの環境変数に格納されます。 この環境変数を取得するには、バッチ ファイルから ERRORLEVEL
を使用するか、PowerShell から $LastExitCode
を使用します。
dotnet CLI の dotnet build
コマンドを使用してアプリケーションを構築できます。
次に、アプリケーションを実行して結果を表示する PowerShell スクリプトを作成します。 次のコードをテキスト ファイルに貼り付け、プロジェクトが保存されているフォルダーに test.ps1
として保存します。 PowerShell プロンプトに「test.ps1
」と入力して PowerShell スクリプトを実行します。
コードがゼロを返すため、バッチ ファイルで成功が報告されます。 ただし、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 の戻り値
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();
}
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();
と同等のコードが生成されます。
注意
この例の Main
メソッドで async
修飾子を使用した場合、同じコードが生成されます。
コマンド ライン引数
Main
メソッドに引数を渡すには、次のいずれかの方法でメソッドを定義します。
Main メソッド コード |
Main シグネチャ |
---|---|
戻り値がなく、await を使用しない |
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) |
引数が使用されない場合、メソッド シグネチャから args
を省略し、少しばかり簡単なコードにすることができます。
Main メソッド コード |
Main シグネチャ |
---|---|
戻り値がなく、await を使用しない |
static void Main() |
戻り値があり、await を使用しない |
static int Main() |
戻り値がなく、await を使用する |
static async Task Main() |
戻り値があり、await を使用する |
static async Task<int> Main() |
注意
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
コンソール アプリケーションでコマンド ライン引数を使用する方法の例を次に示します。 アプリケーションは、実行時に引数を 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) { // Test if input arguments were supplied. if (args.Length == 0) { Console.WriteLine("Please enter a numeric argument."); Console.WriteLine("Usage: Factorial <num>"); return 1; } // Try to convert the input arguments to numbers. This will throw // an exception if the argument is not a number. // num = int.Parse(args[0]); 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; } // Calculate factorial. long result = Functions.Factorial(num); // Print result. if (result == -1) Console.WriteLine("Input must be >= 0 and <= 20."); else Console.WriteLine($"The Factorial of {num} is {result}."); return 0; } } // If 3 is entered on command line, the // output reads: The factorial of 3 is 6.
[スタート] 画面または [スタート] メニューから、Visual Studio の [開発者コマンド プロンプト] ウィンドウを開き、作成したファイルが含まれているフォルダーに移動します。
次のコマンドを入力してアプリケーションをコンパイルします。
dotnet build
アプリケーションにコンパイル エラーがなければ、Factorial.exe という名前の実行可能ファイルが作成されます。
3 の階乗を計算する次のコマンドを入力します。
dotnet run -- 3
次の出力が生成されます:
The factorial of 3 is 6.
注意
Visual Studio でアプリケーションを実行する場合、「[デバッグ] ページ (プロジェクト デザイナー)」のコマンド ライン引数を指定できます。
C# 言語仕様
詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。