ランタイムは、C# アプリケーションの起動時に Main メソッドを呼び出します。
Main メソッドは、C# アプリケーションのエントリ ポイントです
C# プログラムはエントリ ポイントを 1 つだけ持つことができます。
Main メソッドを持つ複数のクラスがある場合は、プログラムをコンパイルするときに 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 <file.cs>を使用するか、最初の行として #!/usr/bin/env dotnet run ディレクティブを使用して実行します (Unix シェルのみ)。
概要
-
Mainメソッドは、実行可能プログラムのエントリ ポイントです。 ここで、プログラム コントロールの開始と終了が行われます。 - クラスまたは構造体内で
Mainを宣言する必要があります。 外側のclassはstaticでもかまいません。 -
Mainは、staticである必要があります。 -
Mainは、任意の アクセス修飾子を持つことができます。 -
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 関数から返された値が環境変数に格納されます。 この環境変数は、バッチ ファイルから ERRORLEVEL を使用するか、PowerShell から $LastExitCode して取得できます。
dotnet CLIdotnet 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