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);
    }
}

アプリケーションのエントリ ポイントとして、1 つのファイル内で最上位レベルのステートメントを使用することもできます。 Main メソッドと同様に、最上位レベルのステートメントも値を返しコマンド ライン引数にアクセスできます。 詳しくは、「最上位レベルのステートメント」を参照してください。

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;

概要

  • Main メソッドは実行可能プログラムのエントリ ポイントであり、ここでプログラムの制御を開始および終了します。
  • Main は、クラスまたは構造体の内部で宣言されます。 Mainstatic とする必要がありますが、public である必要はありません。 (先ほどの例では、既定の private のアクセスを受け取ります)。外側の classstatic でもかまいません。
  • Main の戻り値は、voidintTaskTask<int> のいずれかになります。
  • MainTask または 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 アクセサー修飾子を使用しています。 これは一般的ですが、必須ではありません。

コンソール アプリケーションの Mainawait を使用して非同期操作を開始する必要がある場合、戻り値の型 asyncTaskTask<int> を追加することでプログラム コードを簡略化できます。

Main() の戻り値

次のいずれかの方法でメソッドを定義することで、Main メソッドから int を返すことができます。

Main メソッド コード Main シグネチャ
argsawait は使用しない static int Main()
args を使用し、await を使用しない static int Main(string[] args)
args を使用せず、await を使用する static async Task<int> Main()
argsawait を使用する static async Task<int> Main(string[] args)

Main からの戻り値を使用しない場合、voidTask を返すと少し簡単なコードにすることができます。

Main メソッド コード Main シグネチャ
argsawait は使用しない static void Main()
args を使用し、await を使用しない static void Main(string[] args)
args を使用せず、await を使用する static async Task Main()
argsawait を使用する static async Task Main(string[] args)

ただし、intTask<int> を返すことによって、プログラムが状態の情報を、実行可能ファイルを呼び出す他のプログラムまたはスクリプトに伝達することができます。

次の例からは、プロセスの終了コードにアクセスする方法がわかります。

この例では、.NET Core コマンドライン ツールを使用します。 .NET Core コマンドライン ツールに慣れていない場合は、この概要の記事を参照してください。

dotnet new console を実行して新しいアプリケーションを作成します。 program.csMain メソッドを次のように変更します。

// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
    static int Main()
    {
        //...
        return 0;
    }
}

プログラムを Windows で実行する場合、Main 関数からの戻り値はすべて 1 つの環境変数に格納されます。 この環境変数を取得するには、バッチ ファイルから ERRORLEVEL を使用するか、PowerShell から $LastExitCode を使用します。

dotnet CLIdotnet 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 の戻り値

Mainasync 戻り値を宣言すると、Main 内で非同期メソッドを呼び出すための定型コードがコンパイラによって生成されます。 async キーワードを指定しない場合は、次の例に示すように、そのコードを自分で記述する必要があります。 この例のコードでは、非同期操作が完了するまでプログラムが確実に実行されるようにしています。

class AsyncMainReturnValTest
{
    public static void Main()
    {
        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;
    }
}

Mainasync として宣言することには、コンパイラによって常に正しいコードが生成されるという利点があります。

アプリケーションのエントリ ポイントから 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 メソッドを使用して longParse 値に変換します。

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 つ受け取り、整数に変換し、その値の階乗を計算しています。 引数がない場合は、アプリケーションの正しい使用方法を説明するメッセージを表示します。

コマンド プロンプトからアプリケーションをコンパイルして実行するには、次の手順を実行します。

  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.
    
  2. [スタート] 画面または [スタート] メニューから、Visual Studio の [開発者コマンド プロンプト] ウィンドウを開き、作成したファイルが含まれているフォルダーに移動します。

  3. 次のコマンドを入力してアプリケーションをコンパイルします。

    dotnet build

    アプリケーションにコンパイル エラーがなければ、Factorial.exe という名前の実行可能ファイルが作成されます。

  4. 3 の階乗を計算する次のコマンドを入力します。

    dotnet run -- 3

  5. 次の出力が生成されます: The factorial of 3 is 6.

注意

Visual Studio でアプリケーションを実行する場合、「[デバッグ] ページ (プロジェクト デザイナー)」のコマンド ライン引数を指定できます。

C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。

関連項目