最上位レベルのステートメント - Main メソッドを使用しないプログラム

コンソール アプリケーション プロジェクトに Main メソッドを明示的に含める必要はありません。 代わりに、"最上位レベルのステートメント" 機能を使用し、記述しなければならないコードを最小限に抑えることができます。

最上位レベルのステートメントを使うと、ファイルのルートに実行可能コードを直接記述できるので、コードをクラスやメソッドでラップする必要がなくなります。 つまり、Program クラスと Main メソッドの形式を使わずにプログラムを作成できます。 この場合、アプリケーションに対し、コンパイラで、メソッド エントリ ポイントを含む Program クラスが生成されます。 生成されたメソッドの名前は Main ではありません。これは、コードで直接参照できない実装の詳細です。

次の Program.cs ファイルは、C# 10 の完全な C# プログラムです。

Console.WriteLine("Hello World!");

最上位レベルのステートメントでは、Azure Functions や GitHub Actions など、小さなユーティリティのために簡単なプログラムを記述できます。 また、C# プログラムを始めたばかりの方にとってコードを習い、書くことがもっと簡単になります。

次のセクションでは、最上位レベルのステートメントでできることとできないことに関する規則について説明します。

最上位レベルのファイルは 1 つだけ

アプリケーションに含めるエントリ ポイントは 1 つだけとする必要があります。 プロジェクトには、最上位のステートメントを含むファイルを 1 つだけ含めることができます。 1 つのプロジェクトで複数のファイルに最上位レベルのステートメントを置くと、次のコンパイラ エラーが発生します。

CS8802 トップレベルのステートメントを持つことができるのは、1 つのコンパイル ユニットのみです。

1 つのプロジェクトには、最上位レベルのステートメントが含まれていない追加のソース コード ファイルをいくらでも含めることができます。

エントリ ポイントは他に用意しない

Main メソッドは明示的に記述できますが、エントリ ポイントとして機能させることができません。 コンパイラから次の警告が出ます。

CS7022 プログラムのエントリ ポイントは、グローバル コードです。エントリ ポイント 'Main()' を無視します。

最上位レベルのステートメントが含まれるプロジェクトでは、そのプロジェクトに Main メソッドが複数含まれる場合でも、-main コンパイラ オプションを使用してエントリ ポイントを選択することができません。

using ディレクティブ

using ディレクティブを含める場合、次の例のように、ファイルの先頭に指定する必要があります。

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;

グローバル名前空間

最上位レベルのステートメントは暗黙的にグローバル名前空間に属します。

名前空間と型の定義

最上位レベルのステートメントが含まれるファイルには、名前空間と型の定義を含めることもできますが、最上位レベルのステートメントの後に指定する必要があります。 次に例を示します。

MyClass.TestMethod();
MyNamespace.MyClass.MyMethod();

public class MyClass
{
    public static void TestMethod()
    {
        Console.WriteLine("Hello World!");
    }
}

namespace MyNamespace
{
    class MyClass
    {
        public static void MyMethod()
        {
            Console.WriteLine("Hello World from MyNamespace.MyClass.MyMethod!");
        }
    }
}

args

最上位レベルのステートメントでは、コマンドライン引数が入力された場合、args 変数を参照してそれにアクセスできます。 args 変数が null 値になることはありませんが、その Length は、コマンドライン引数が指定されなかった場合、ゼロになります。 次に例を示します。

if (args.Length > 0)
{
    foreach (var arg in args)
    {
        Console.WriteLine($"Argument={arg}");
    }
}
else
{
    Console.WriteLine("No arguments");
}

await

await を使用して非同期メソッドを呼び出すことができます。 次に例を示します。

Console.Write("Hello ");
await Task.Delay(5000);
Console.WriteLine("World!");

プロセスの終了コード

アプリケーションの終了時に int 値を返すには、int を返す Main メソッドの場合と同じように、return ステートメントを使用します。 次に例を示します。

string? s = Console.ReadLine();

int returnValue = int.Parse(s ?? "-1");
return returnValue;

暗黙的なエントリ ポイント メソッド

最上位レベルのステートメントが含まれるプロジェクトに対して、プログラムのエントリ ポイントとして機能するメソッドがコンパイラによって生成されます。 メソッドのシグネチャは、最上位レベルのステートメントに await キーワードか return ステートメントが含まれるかどうかによって決まります。 メソッド シグネチャがどのように表現されるかを次の表にまとめてあります。便宜上、表ではメソッド名に Main を使用しています。

最上位レベルのコードに含まれる 暗黙的 Main シグネチャ
await および return static async Task<int> Main(string[] args)
await static async Task Main(string[] args)
return static int Main(string[] args)
awaitreturn もない static void Main(string[] args)

C# 言語仕様

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

機能の仕様 - 上位レベルのステートメント