【C#】Mainメソッドとは?プログラムの入口・書き方・引数を初心者向けに解説

はじめに

C#でコンソールアプリケーションを学び始めると、最初に登場しやすいのがMainメソッドです。

C#
static void Main()
{
Console.WriteLine("Hello, World!");
}

このMainメソッドは、C#プログラムが実行されるときの「入口」となる特別なメソッドです。初心者のうちは「なぜMainという名前なのか」「staticやvoidは何を意味するのか」「最近のC#ではMainが見えないことがあるのはなぜか」と疑問に感じることも多いでしょう。

この記事では、C#のMainメソッドについて、プログラムの入口としての役割、基本的な書き方、引数args、戻り値int、トップレベルステートメントとの違い、よくあるエラーまで初心者向けにわかりやすく解説します。

1. C#のMainメソッドとは?プログラムの最初に実行される入口

1-1. MainメソッドはC#アプリケーションのエントリーポイント

C#のMainメソッドは、アプリケーションを起動したときに最初に実行される場所です。このようなプログラムの開始地点を「エントリーポイント」と呼びます。

たとえば、次のようなコードがあるとします。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("プログラムを開始します");
}
}

このプログラムを実行すると、Mainメソッドの中に書かれた処理が最初に動きます。そのため、C#のコンソールアプリケーションでは、まずMainメソッドを理解することが重要です。

Mainメソッドは、単なる普通のメソッドではなく、C#プログラム全体の実行開始位置を表す特別なメソッドです。

1-2. プログラム起動時にMainメソッドが呼び出される流れ

C#プログラムを実行すると、内部的には次のような流れで処理が始まります。

  1. アプリケーションが起動する

  2. 実行環境がエントリーポイントを探す

  3. Mainメソッドが見つかる

  4. Mainメソッドの中の処理が上から順番に実行される

  5. Mainメソッドが終わるとプログラムも終了する

たとえば、次のコードでは、表示される順番は上から順になります。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("1番目の処理");
Console.WriteLine("2番目の処理");
Console.WriteLine("3番目の処理");
}
}

実行結果は次のようになります。

1番目の処理
2番目の処理
3番目の処理

このように、MainメソッドはC#プログラムのスタート地点であり、基本的には中に書いた処理が上から順番に実行されます。

1-3. Mainメソッドがないとどうなるのか

従来のC#のコンソールアプリケーションでは、Mainメソッドがないと、プログラムの開始地点がわからないためエラーになります。

たとえば、次のようにMainメソッドがないコードを考えます。

C#
using System;

class Program
{
static void Hello()
{
Console.WriteLine("こんにちは");
}
}

このコードにはHelloメソッドがありますが、どこから実行を始めればよいのかがわかりません。そのため、コンパイラは「エントリーポイントが見つからない」という内容のエラーを出します。

ただし、C# 9.0以降では「トップレベルステートメント」という書き方が使えるため、見た目上はMainメソッドを書かなくても動く場合があります。これは後ほど詳しく解説します。

1-4. Mainメソッドが必要なプロジェクトと不要なプロジェクト

Mainメソッドが必要かどうかは、プロジェクトの種類によって異なります。

コンソールアプリケーションでは、プログラムを直接起動するため、基本的にエントリーポイントが必要です。そのため、従来の書き方ではMainメソッドを用意します。

一方、クラスライブラリのように、ほかのアプリケーションから呼び出されることを目的としたプロジェクトでは、単体で起動する入口が必要ないため、通常はMainメソッドを書きません。

また、ASP.NET CoreのWebアプリケーションでは、内部的にはエントリーポイントがありますが、テンプレートによってはMainメソッドが直接見えない形で書かれていることがあります。最近の.NETではトップレベルステートメントが使われることが多いため、初心者が「Mainメソッドがないのに実行できる」と感じることがあります。

2. Mainメソッドの基本的な書き方

2-1. 最も基本的なMainメソッドのコード例

C#のMainメソッドの基本形は次のとおりです。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

このコードを実行すると、画面に次のように表示されます。

Hello, World!

初心者が最初に覚えるなら、まずはこの形で十分です。

C#
static void Main()
{
// ここに最初に実行したい処理を書く
}

Mainメソッドの中に書いた処理が、プログラム起動時に実行されます。

2-2. static void Main()の意味

static void Main()は、いくつかの要素に分けて考えると理解しやすくなります。

C#
static void Main()

staticは、インスタンスを作らなくても呼び出せることを表します。プログラム開始時には、まだクラスのオブジェクトが作られていないため、Mainメソッドは基本的にstaticである必要があります。

voidは、戻り値を返さないことを表します。つまり、Mainメソッドの処理が終わっても、呼び出し元に特別な値を返さないという意味です。

Mainはメソッド名です。C#では、この名前がエントリーポイントとして特別に扱われます。

()は引数がないことを表します。つまり、外部から値を受け取らずに実行するMainメソッドです。

まとめると、static void Main()は「インスタンスを作らずに呼び出せる、戻り値なしの、プログラムの入口となるメソッド」という意味になります。

2-3. class ProgramとMainメソッドの関係

C#では、メソッドは基本的にクラスの中に書きます。そのため、従来の書き方ではMainメソッドもクラスの中に書きます。

C#
class Program
{
static void Main()
{
Console.WriteLine("開始");
}
}

この例では、Programというクラスの中にMainメソッドがあります。

Programという名前はよく使われますが、必ずこの名前でなければならないわけではありません。次のように別のクラス名でも、正しいMainメソッドがあれば実行できます。

C#
using System;

class MyApplication
{
static void Main()
{
Console.WriteLine("実行されました");
}
}

重要なのは、クラス名がProgramであることではなく、正しい形式のMainメソッドが存在することです。

2-4. Console.WriteLineを使った実行例

Mainメソッドの動きを確認するには、Console.WriteLineを使うとわかりやすいです。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("C#の学習を開始します");
Console.WriteLine("Mainメソッドが実行されています");
}
}

実行結果は次のようになります。

C#の学習を開始します
Mainメソッドが実行されています

Console.WriteLineは、コンソール画面に文字列を表示する命令です。Mainメソッドの中に書くことで、プログラム起動時にそのメッセージが表示されます。

初心者のうちは、Mainメソッドの中にConsole.WriteLineを書いて、どの処理がどの順番で動くのかを確認すると理解しやすくなります。

2-5. Mainは大文字で書く必要があるのか

C#では、大文字と小文字が区別されます。そのため、エントリーポイントとして認識されるメソッド名はMainであり、mainではありません。

次のように小文字で書くと、通常はエントリーポイントとして認識されません。

C#
class Program
{
static void main()
{
Console.WriteLine("これはMainではありません");
}
}

C#では、Mainmainは別の名前として扱われます。検索キーワードとして「c# main」と入力することは多いですが、実際のコードではMainのように先頭を大文字で書く必要があります。

3. Mainメソッドで使える戻り値と引数のパターン

3-1. static void Main()の書き方

最もシンプルな形がstatic void Main()です。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("引数なし、戻り値なしのMainメソッドです");
}
}

この形は、外部から値を受け取らず、終了時に値も返さない書き方です。

初心者がC#の基本を学ぶときは、まずこの形から始めるのがおすすめです。余計な要素が少ないため、Mainメソッドの役割に集中できます。

3-2. static void Main(string[] args)の書き方

コマンドライン引数を受け取りたい場合は、次のようにstring[] argsを指定します。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine("引数の数: " + args.Length);
}
}

argsには、プログラム実行時に渡された文字列が配列として入ります。

たとえば、コマンドラインで次のように実行したとします。

dotnet run apple banana

この場合、args[0]にはappleargs[1]にはbananaが入ります。

3-3. static int Main()の書き方

Mainメソッドは、intを戻り値として返すこともできます。

C#
using System;

class Program
{
static int Main()
{
Console.WriteLine("正常終了します");
return 0;
}
}

intを返すMainメソッドでは、最後にreturnで整数を返します。この整数は、プログラムの終了コードとして使われます。

一般的には、0は正常終了、0以外は異常終了を表すことが多いです。

3-4. static int Main(string[] args)の書き方

引数を受け取り、さらに終了コードも返したい場合は、次のように書きます。

C#
using System;

class Program
{
static int Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("引数が指定されていません");
return 1;
}

Console.WriteLine("最初の引数: " + args[0]);
return 0;
}
}

この例では、引数がない場合は1を返し、引数がある場合は0を返しています。

このような書き方は、バッチ処理や自動実行されるツールでよく使われます。実行結果が成功だったのか失敗だったのかを、終了コードで判断できるからです。

3-5. C# 7.1以降で使えるasync Task Mainの書き方

C# 7.1以降では、非同期処理を扱うためにasync Task Mainを使えます。

C#
using System;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
Console.WriteLine("非同期処理を開始します");

await Task.Delay(1000);

Console.WriteLine("非同期処理が完了しました");
}
}

async Task Mainを使うと、Mainメソッドの中でawaitを直接使えます。

また、引数を受け取る形も書けます。

C#
using System;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
await Task.Delay(1000);
Console.WriteLine("引数の数: " + args.Length);
}
}

終了コードを返したい場合は、Task<int>を使います。

C#
using System;
using System.Threading.Tasks;

class Program
{
static async Task<int> Main(string[] args)
{
await Task.Delay(1000);

if (args.Length == 0)
{
return 1;
}

return 0;
}
}

非同期処理とは、時間のかかる処理を待っている間に、プログラム全体を効率よく動かすための仕組みです。ファイル読み込み、ネットワーク通信、Web API呼び出しなどでよく使われます。

3-6. どのMainメソッドを使えばよいか初心者向けに比較

初心者は、まずstatic void Main()から覚えるのがおすすめです。理由は、最もシンプルで理解しやすいからです。

コマンドライン引数を使いたい場合は、static void Main(string[] args)を使います。

終了コードを返したい場合は、static int Main()またはstatic int Main(string[] args)を使います。

非同期処理を使いたい場合は、static async Task Main()またはstatic async Task<int> Main()を使います。

学習の順番としては、次のように進めると理解しやすいです。

static void Main()

static void Main(string[] args)

static int Main(string[] args)

static async Task Main()

最初からすべてを覚える必要はありません。まずは「Mainメソッドはプログラムの入口である」と理解することが大切です。

4. Mainメソッドの引数argsとは?コマンドライン引数の使い方

4-1. string[] argsの意味

string[] argsは、文字列の配列を受け取るための引数です。

C#
static void Main(string[] args)

stringは文字列を表します。[]は配列を表します。つまり、string[]は「文字列を複数入れられる配列」という意味です。

argsは引数名です。名前は慣習的にargsが使われますが、別の名前にすることもできます。

C#
static void Main(string[] values)
{
Console.WriteLine(values.Length);
}

ただし、一般的にはargsと書くことが多いため、初心者はstring[] argsで覚えておくとよいでしょう。

4-2. コマンドライン引数とは何か

コマンドライン引数とは、プログラムを実行するときに外部から渡す値のことです。

たとえば、次のように実行したとします。

dotnet run taro 25

この場合、taro25がコマンドライン引数です。

C#のプログラム側では、これらの値をargsで受け取れます。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine(args[0]);
Console.WriteLine(args[1]);
}
}

この例では、args[0]taroargs[1]25になります。

コマンドライン引数を使うと、プログラムの動作を実行時に変えられます。

4-3. argsに値を渡して実行する方法

.NETのコンソールアプリケーションで引数を渡す場合、dotnet runの後に引数を書きます。

dotnet run apple banana orange

このように実行すると、argsには次のように値が入ります。

args[0] = "apple"
args[1] = "banana"
args[2] = "orange"

プログラム側では次のように受け取れます。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine(args[0]);
Console.WriteLine(args[1]);
Console.WriteLine(args[2]);
}
}

ただし、引数の数が足りない状態でargs[2]のようにアクセスするとエラーになるため、実際にはargs.Lengthで数を確認してから使うのが安全です。

4-4. argsの中身を表示するサンプルコード

argsの中身をすべて表示するには、foreach文を使うと便利です。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine("受け取った引数:");

foreach (string arg in args)
{
Console.WriteLine(arg);
}
}
}

次のように実行します。

dotnet run red green blue

実行結果は次のようになります。

受け取った引数:
red
green
blue

foreach文を使うと、配列の中身を1つずつ取り出して処理できます。コマンドライン引数の数が毎回変わる場合でも、すべての引数を順番に処理できるため便利です。

4-5. 引数がない場合の注意点

argsを使うときに注意したいのは、引数が必ず渡されるとは限らないことです。

たとえば、次のコードは危険です。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine(args[0]);
}
}

引数を指定せずに実行すると、args[0]が存在しないためエラーになります。

安全に書くには、次のようにargs.Lengthを確認します。

C#
using System;

class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("引数が指定されていません");
return;
}

Console.WriteLine("最初の引数: " + args[0]);
}
}

初心者は、args[0]を使う前に、必ずargs.Lengthで引数の数を確認する習慣をつけるとよいでしょう。

5. Mainメソッドの戻り値intとは?終了コードの使い方

5-1. voidとintの違い

Mainメソッドの戻り値には、主にvoidintがあります。

voidは、値を返さないことを表します。

C#
static void Main()
{
Console.WriteLine("終了コードを明示的には返しません");
}

一方、intは整数を返すことを表します。

C#
static int Main()
{
Console.WriteLine("終了コードを返します");
return 0;
}

voidはシンプルに書けるため、初心者向けです。intは、プログラムの終了結果を外部に伝えたいときに使います。

5-2. 終了コードとは何か

終了コードとは、プログラムが終了したときにOSや呼び出し元へ返す数値です。

たとえば、自動実行の処理では、プログラムが成功したのか失敗したのかを判断する必要があります。そのときに終了コードが使われます。

一般的には、次のように考えます。

0     正常終了
0以外 異常終了

C#では、int Main()を使うことで終了コードを明示的に返せます。

C#
static int Main()
{
return 0;
}

この場合、プログラムは正常終了したことを表します。

5-3. return 0とreturn 1の意味

return 0は、一般的に正常終了を意味します。

C#
static int Main()
{
Console.WriteLine("正常に完了しました");
return 0;
}

return 1は、一般的に何らかのエラーや異常終了を意味します。

C#
static int Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("エラー: 引数が必要です");
return 1;
}

Console.WriteLine("処理を実行しました");
return 0;
}

ただし、1だけがエラーを表すと決まっているわけではありません。プログラムによっては、エラーの種類ごとに23などを使い分けることもあります。

5-4. バッチ処理や自動実行で終了コードを使う場面

終了コードは、バッチ処理、スクリプト、自動実行、CI/CDなどで役立ちます。

たとえば、あるC#プログラムを自動実行して、成功した場合だけ次の処理に進みたいとします。このとき、終了コードが0なら成功、0以外なら失敗として判断できます。

次のようなプログラムを考えます。

C#
using System;

class Program
{
static int Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("ファイル名を指定してください");
return 1;
}

Console.WriteLine("処理対象ファイル: " + args[0]);
return 0;
}
}

このように、引数が足りない場合に1を返せば、呼び出し元のスクリプトがエラーとして扱いやすくなります。

5-5. 初心者はvoidとintのどちらを使うべきか

初心者が学習目的でC#を書く場合は、まずvoidで問題ありません。

C#
static void Main()
{
Console.WriteLine("学習用のプログラムです");
}

理由は、終了コードを意識しなくてもプログラムの基本を学べるからです。

一方で、コマンドラインツールや自動実行されるプログラムを作る場合は、intを使うと便利です。

学習初期はstatic void Main()、少し慣れてきたらstatic int Main(string[] args)を使う、と段階的に覚えるとよいでしょう。

6. C# 9.0以降のトップレベルステートメントとMainメソッドの違い

6-1. トップレベルステートメントとは

トップレベルステートメントとは、class Programstatic void Main()を書かずに、直接処理を書けるC#の構文です。

たとえば、次のように書けます。

C#
Console.WriteLine("Hello, World!");

これだけでコンソールアプリケーションとして実行できます。

従来の書き方では、次のように書く必要がありました。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

トップレベルステートメントを使うと、初心者でも短いコードでプログラムを実行できます。

6-2. Mainメソッドを書かなくても実行できる理由

トップレベルステートメントでは、開発者がMainメソッドを明示的に書かなくても、コンパイラが内部的にエントリーポイントを作ってくれます。

つまり、Mainメソッドが完全になくなったわけではありません。見た目上は書かれていないだけで、プログラムの入口に相当する処理は内部的に存在します。

次のトップレベルステートメントは、

C#
Console.WriteLine("Hello");

イメージとしては、次のようなMainメソッド形式に近いものとして扱われます。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello");
}
}

そのため、C# 9.0以降の新しい書き方では「Mainメソッドが見えないのに実行できる」という状態になります。

6-3. Visual Studioや.NETの新しいテンプレートでMainが見えない理由

Visual Studioや.NETの新しいコンソールアプリテンプレートでは、トップレベルステートメントが使われることがあります。

そのため、新しくプロジェクトを作成すると、最初から次のようなコードになっている場合があります。

C#
Console.WriteLine("Hello, World!");

初心者は「class Programはどこにあるのか」「Mainメソッドはどこにあるのか」と混乱するかもしれません。

これは、C#の新しい構文によって、シンプルに書けるようになったためです。従来のMainメソッド形式が使えなくなったわけではありません。必要であれば、自分でclass ProgramMainメソッドを書くこともできます。

6-4. トップレベルステートメントをMainメソッド形式に書き換える方法

トップレベルステートメントのコードは、従来のMainメソッド形式に書き換えられます。

たとえば、次のコードがあるとします。

C#
Console.WriteLine("こんにちは");
Console.WriteLine("C#を学習中です");

これをMainメソッド形式にすると、次のようになります。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("こんにちは");
Console.WriteLine("C#を学習中です");
}
}

コマンドライン引数を使う場合、トップレベルステートメントではargsをそのまま使えます。

C#
Console.WriteLine(args.Length);

Mainメソッド形式に書き換えると、次のようになります。

C#
using System;

class Program
{
static void Main(string[] args)
{
Console.WriteLine(args.Length);
}
}

このように、トップレベルステートメントとMainメソッド形式は、見た目は違っても、プログラムの入口を書くという意味ではつながっています。

6-5. 初心者はどちらの書き方で学ぶべきか

初心者がC#を学ぶ場合、最初はトップレベルステートメントのほうが簡単に感じるかもしれません。

C#
Console.WriteLine("Hello, World!");

短く書けるため、最初の一歩としてはわかりやすいです。

しかし、C#の仕組みをしっかり理解したいなら、Mainメソッド形式も学ぶべきです。

C#
class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

特に、staticvoidstring[] args、クラス、メソッドといったC#の基本を理解するには、Mainメソッド形式が役立ちます。

おすすめは、最初にトップレベルステートメントで動かす楽しさを知り、その後でMainメソッド形式を学ぶ流れです。

7. Mainメソッドでよくあるエラーと対処法

7-1. 「Mainメソッドが見つかりません」と表示される原因

「Mainメソッドが見つかりません」というエラーは、プログラムの入口が見つからないときに発生します。

よくある原因は次のとおりです。

Mainの名前を間違えている
staticを書き忘れている
戻り値や引数の形が正しくない
実行できない種類のプロジェクトを起動しようとしている

たとえば、次のコードはmainが小文字なので、エントリーポイントとして認識されません。

C#
class Program
{
static void main()
{
Console.WriteLine("小文字のmainです");
}
}

正しくは次のようにMainと書きます。

C#
class Program
{
static void Main()
{
Console.WriteLine("大文字のMainです");
}
}

C#は大文字と小文字を区別するため、Mainの大文字・小文字には注意しましょう。

7-2. Mainメソッドを複数書いたときのエラー

1つのプロジェクト内に有効なMainメソッドが複数あると、どれを入口にすればよいのか判断できず、エラーになることがあります。

C#
class Program1
{
static void Main()
{
Console.WriteLine("Program1");
}
}

class Program2
{
static void Main()
{
Console.WriteLine("Program2");
}
}

このような場合、コンパイラはエントリーポイントを1つに決められません。

対処法としては、不要なMainメソッドを削除するか、プロジェクトの設定でどのMainメソッドを使うか指定します。

初心者の場合は、まず1つのプロジェクトにMainメソッドは1つだけ書く、と覚えておくとよいでしょう。

7-3. staticを書き忘れたときのエラー

Mainメソッドでstaticを書き忘れると、エントリーポイントとして認識されない場合があります。

間違った例は次のとおりです。

C#
class Program
{
void Main()
{
Console.WriteLine("staticがありません");
}
}

正しくは次のように書きます。

C#
class Program
{
static void Main()
{
Console.WriteLine("staticがあります");
}
}

プログラム起動時には、まだProgramクラスのインスタンスが作られていません。そのため、インスタンスを作らずに呼び出せるstaticメソッドとしてMainを書く必要があります。

7-4. 戻り値や引数の書き方を間違えたときのエラー

Mainメソッドには、エントリーポイントとして認められる形があります。

代表的な形は次のとおりです。

C#
static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
static async Task Main()
static async Task Main(string[] args)
static async Task<int> Main()
static async Task<int> Main(string[] args)

たとえば、次のような戻り値は通常のエントリーポイントとしては適切ではありません。

C#
static string Main()
{
return "Hello";
}

Mainメソッドの戻り値には、voidint、非同期の場合はTaskTask<int>を使います。

初心者のうちは、まずstatic void Main()またはstatic void Main(string[] args)の形を使うと間違いにくいです。

7-5. トップレベルステートメントとMainメソッドを混在させたときの注意点

トップレベルステートメントを使っているファイルに、明示的なMainメソッドを追加すると、エントリーポイントが重複してエラーになることがあります。

たとえば、次のような書き方は避けます。

C#
Console.WriteLine("トップレベルステートメントです");

class Program
{
static void Main()
{
Console.WriteLine("Mainメソッドです");
}
}

この場合、トップレベルステートメント自体がエントリーポイントを作るため、明示的なMainメソッドと競合する可能性があります。

対処法は、どちらか一方の書き方に統一することです。

トップレベルステートメントで書くなら、Mainメソッドを書かずに直接処理を書きます。

C#
Console.WriteLine("Hello, World!");

Mainメソッド形式で書くなら、トップレベルに直接処理を書かず、クラスとMainメソッドの中に処理を書きます。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

8. Mainメソッドを使った初心者向けサンプルコード

8-1. Hello Worldを表示するサンプル

まずは、最も基本的なHello Worldのサンプルです。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

このコードでは、Mainメソッドが実行され、Console.WriteLineによって文字列が表示されます。

実行結果は次のとおりです。

Hello, World!

C#の学習では、このような短いプログラムから始めると、Mainメソッドの役割を理解しやすくなります。

8-2. 引数を受け取って表示するサンプル

次に、string[] argsを使って引数を受け取るサンプルです。

C#
using System;

class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("引数がありません");
return;
}

Console.WriteLine("受け取った引数:");

foreach (string arg in args)
{
Console.WriteLine(arg);
}
}
}

次のように実行します。

dotnet run apple banana

実行結果は次のようになります。

受け取った引数:
apple
banana

このサンプルでは、引数がない場合にもエラーにならないように、args.Lengthで確認しています。

8-3. 終了コードを返すサンプル

次は、int Mainを使って終了コードを返すサンプルです。

C#
using System;

class Program
{
static int Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("エラー: 名前を指定してください");
return 1;
}

Console.WriteLine("こんにちは、" + args[0] + "さん");
return 0;
}
}

引数がない場合は1を返し、引数がある場合は0を返します。

このように書くことで、プログラムを呼び出した側が成功・失敗を判断しやすくなります。

8-4. async Task Mainで非同期処理を実行するサンプル

非同期処理を使う場合は、async Task Mainを使えます。

C#
using System;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
Console.WriteLine("処理を開始します");

await Task.Delay(1000);

Console.WriteLine("1秒後に処理が完了しました");
}
}

await Task.Delay(1000)は、1秒待つ処理です。

async Task Mainを使うことで、Mainメソッドの中で自然にawaitを書けます。Web APIの呼び出しやファイル操作など、時間のかかる処理を扱うときに便利です。

8-5. サンプルコードの実行手順

.NET CLIを使ってコンソールアプリを作成・実行する基本手順は次のとおりです。

まず、コンソールアプリを作成します。

dotnet new console -n MainSample

作成したフォルダに移動します。

cd MainSample

Program.csを編集し、サンプルコードを書きます。

その後、次のコマンドで実行します。

dotnet run

引数を渡したい場合は、次のように実行します。

dotnet run apple banana

C#のMainメソッドを理解するには、実際にコードを書いて実行することが大切です。エラーが出た場合も、Mainの名前、static、戻り値、引数の形を確認すると原因を見つけやすくなります。

9. Mainメソッドを理解するために知っておきたい関連知識

9-1. メソッドとは何か

メソッドとは、処理をひとまとまりにしたものです。

たとえば、次のコードではSayHelloがメソッドです。

C#
using System;

class Program
{
static void Main()
{
SayHello();
}

static void SayHello()
{
Console.WriteLine("こんにちは");
}
}

Mainメソッドの中からSayHelloメソッドを呼び出しています。

メソッドを使うと、処理を分けて整理できます。プログラムが大きくなるほど、すべてをMainメソッドに書くのではなく、複数のメソッドに分けることが重要になります。

9-2. staticとは何か

staticは、クラスのインスタンスを作らなくても使えることを表します。

通常、クラスのメソッドを使うには、次のようにインスタンスを作ることがあります。

C#
MyClass obj = new MyClass();
obj.Hello();

しかし、staticメソッドはインスタンスを作らずに呼び出せます。

C#
MyClass.Hello();

Mainメソッドはプログラム開始時に呼び出されるため、インスタンスを作る前に実行できる必要があります。そのため、基本的にstaticとして書きます。

9-3. voidとは何か

voidは、メソッドが値を返さないことを表します。

C#
static void SayHello()
{
Console.WriteLine("こんにちは");
}

このメソッドは、画面に文字を表示しますが、呼び出し元に値を返しません。

一方、値を返すメソッドは次のように書きます。

C#
static int Add(int a, int b)
{
return a + b;
}

このメソッドは、計算結果をintとして返します。

Mainメソッドでも、値を返さない場合はvoid、終了コードを返す場合はintを使います。

9-4. string[]とは何か

string[]は、文字列の配列を表します。

C#
string[] fruits = { "apple", "banana", "orange" };

配列の中身には、番号を使ってアクセスします。

C#
Console.WriteLine(fruits[0]);
Console.WriteLine(fruits[1]);
Console.WriteLine(fruits[2]);

実行結果は次のようになります。

apple
banana
orange

Mainメソッドのstring[] argsも、これと同じく文字列の配列です。プログラム実行時に渡された引数が、順番に配列へ入ります。

9-5. publicとprivateはMainメソッドに必要なのか

Mainメソッドには、publicprivateを付けることもできますが、必ず必要というわけではありません。

たとえば、次のように書けます。

C#
class Program
{
public static void Main()
{
Console.WriteLine("public Main");
}
}

また、次のように書くこともできます。

C#
class Program
{
private static void Main()
{
Console.WriteLine("private Main");
}
}

アクセス修飾子を省略した次の書き方もよく使われます。

C#
class Program
{
static void Main()
{
Console.WriteLine("Main");
}
}

初心者のうちは、まずstatic void Main()と書けば十分です。アクセス修飾子については、クラスやメソッドの公開範囲を学ぶ段階で理解すれば問題ありません。

10. C#のMainメソッドに関するよくある質問

10-1. Mainメソッドは必ず1つだけ必要ですか

基本的に、1つの実行可能なアプリケーションには、エントリーポイントが1つ必要です。

Mainメソッドを複数書くこと自体はできますが、どれを入口にするか指定しないとエラーになることがあります。初心者は、1つのプロジェクトにMainメソッドは1つだけと考えるとわかりやすいです。

トップレベルステートメントを使う場合は、明示的なMainメソッドを書かなくても、内部的に入口が作られます。

10-2. Mainメソッドの名前を変更できますか

エントリーポイントとして使うメソッド名は、基本的にMainです。

StartRunなど、別の名前に変更すると、通常はプログラムの入口として認識されません。

C#
class Program
{
static void Start()
{
Console.WriteLine("これはエントリーポイントではありません");
}
}

このようなメソッドは普通のメソッドとしては使えますが、アプリケーションの開始地点にはなりません。

C#では、エントリーポイントとして認識させるにはMainという名前を使う、と覚えておきましょう。

10-3. Mainメソッドはどのクラスに書いてもよいですか

Mainメソッドは、必ずしもProgramクラスに書く必要はありません。

C#
using System;

class App
{
static void Main()
{
Console.WriteLine("AppクラスのMainです");
}
}

このように、別のクラス名でも有効なMainメソッドがあれば実行できます。

ただし、慣習的にはProgramクラスに書くことが多いです。特に初心者向けの教材やサンプルでは、class Programの中にMainメソッドを書く形がよく使われます。

10-4. Mainメソッドから別のメソッドを呼び出すにはどうすればよいですか

Mainメソッドから別のメソッドを呼び出すには、メソッド名を書いて呼び出します。

C#
using System;

class Program
{
static void Main()
{
ShowMessage();
}

static void ShowMessage()
{
Console.WriteLine("別のメソッドを呼び出しました");
}
}

実行結果は次のようになります。

別のメソッドを呼び出しました

このように、Mainメソッドはプログラム全体の流れを管理し、具体的な処理は別のメソッドに分けると、コードが読みやすくなります。

10-5. WebアプリやライブラリにもMainメソッドは必要ですか

クラスライブラリには、通常Mainメソッドは必要ありません。ライブラリは単体で実行するものではなく、ほかのアプリケーションから呼び出されるものだからです。

Webアプリケーションの場合は、アプリケーションとして起動するための入口は必要です。ただし、最近のASP.NET Coreテンプレートでは、トップレベルステートメントを使っていることがあり、明示的なMainメソッドが見えない場合があります。

つまり、Webアプリでは入口が存在しないわけではなく、書き方が簡略化されていることがある、という理解が正確です。

10-6. Mainメソッドとコンストラクタの違いは何ですか

Mainメソッドは、プログラム全体の実行開始地点です。

一方、コンストラクタは、クラスのインスタンスを作成するときに呼び出される特別な処理です。

C#
using System;

class Person
{
public Person()
{
Console.WriteLine("Personのコンストラクタです");
}
}

class Program
{
static void Main()
{
Person person = new Person();
}
}

このコードでは、まずMainメソッドが実行されます。その中でnew Person()が実行されると、Personクラスのコンストラクタが呼び出されます。

つまり、Mainメソッドはプログラムの入口であり、コンストラクタはオブジェクト作成時の初期化処理です。役割がまったく異なります。

まとめ

C#のMainメソッドは、プログラムが最初に実行される入口です。従来のコンソールアプリケーションでは、class Programの中にstatic void Main()を書く形がよく使われます。

基本形は次のとおりです。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
}
}

staticはインスタンスを作らずに呼び出せること、voidは戻り値がないこと、Mainはプログラムの入口となる特別なメソッド名を表します。

コマンドライン引数を受け取りたい場合は、static void Main(string[] args)を使います。終了コードを返したい場合は、static int Main()static int Main(string[] args)を使います。非同期処理を行いたい場合は、C# 7.1以降でasync Task Mainを使えます。

また、C# 9.0以降ではトップレベルステートメントにより、Mainメソッドを明示的に書かなくてもプログラムを実行できます。ただし、内部的にはエントリーポイントに相当する処理が作られているため、Mainメソッドの考え方を理解しておくことは大切です。

初心者はまず、static void Main()の形でC#プログラムの流れを理解しましょう。その後、argsによる引数の受け取り、intによる終了コード、async Task Mainによる非同期処理へと学習を広げていくと、C#のプログラム構造をより深く理解できます。