最初のプログラムの定番は、1行のテキストを表示するものです。C#では次のようになります。
出力:
Hello, World!
1行ずつ見る
using System;を書くと、完全な名前System.Consoleの代わりにConsoleと書けます。ConsoleはSystem名前空間のクラスです(名前空間とusingを参照)。class Programはクラスを宣言します。C#のすべてのコードは型の中にあります。Programという名前は慣例であって、必須ではありません。static void Main()はエントリポイントです。プログラムが始まると、ランタイムはMainという名前の静的メソッドを探して呼び出します。staticはクラス自体に属することを意味するので、先にオブジェクトを作る必要はありません。voidは何も返さないことを意味します。Console.WriteLine("Hello, World!");は、文字列の引数を付けてWriteLineメソッドを呼び出します。すべての文はセミコロンで終わります。- 波かっこ
{ }は、クラスとメソッドの本体を表します。
C#は大文字と小文字を区別します。console.writeline と main は Console.WriteLine と Main とは別の名前で、どちらも存在しません。
Console.WriteLineとConsole.Write
WriteLine はテキストの後に改行を加えます。Write は加えないので、次の出力は同じ行に続きます。どちらも文字列だけでなく任意の型を受け付けます。数値、ブール値、オブジェクトは ToString() メソッドで変換されます。
出力:
Loading.. done
42
True
Item: coffee
coffee costs 3.20
coffee costs 3.20
true が True と表示されることに注目してください。これは bool.ToString() が返すものです。文字列補間と呼ばれる $"..." の形が、最もよく使うものになります。:F2 のような書式コードについては文字列補間を参照してください。
Console.ReadLineで入力を読む
Console.ReadLine() は、ユーザーが1行入力してEnterを押すのを待ち、その行を改行なしの string として返します。入力の終わり(たとえば、ファイルからリダイレクトされた入力が尽きたとき)には null を返します。
出力:
What is your name? How old are you?
Hi Maya, next year you will be 28.
これをターミナルで実行すると、入力したテキストが各プロンプトの後に表示されます。上の出力に入力したテキストがないのは、入力を打ち込んだのではなくリダイレクト(パイプ)したので、プログラム自身が書き出したものだけが表示されているからです。
ReadLine は常にテキストを返します。値を数値として使うには変換が必要です。int.Parse(text) はテキストが数値でないと FormatException を投げます。int.TryParse は代わりに false を返すので、ユーザーの入力にはこちらが適しています。詳しくは型変換で扱います。
関連するメソッドが2つあります。Console.Read() は次の文字を int のコードとして返し、Console.ReadKey() はEnterを待たずに1回のキー入力を読みます(対話的なターミナルでしか動きません)。
Mainメソッドの他の形
Main はコマンドライン引数を受け取ることができ、終了コードを返すこともできます。次のどれも有効なエントリポイントです。
static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
static async Task Main() // C# 7.1 and later
static async Task<int> Main(string[] args) // C# 7.1 and later
返された int はプロセスの終了コードになり、スクリプトやCIシステムはそれを読んでプログラムが成功したかどうかを判断します(慣例で0が成功です)。
出力:
Got 0 argument(s)
dotnet run -- apples pears で実行すると、args には "apples" と "pears" が入ります。-- は、プログラムへの引数と dotnet ツールへの引数を区切ります。
コメント
C#には3種類のコメントがあります。コンパイラはそのすべてを無視します。
// A single-line comment runs to the end of the line.
/* A block comment
can span several lines. */
/// <summary>
/// An XML documentation comment. Editors show it as the tooltip for the method.
/// </summary>
static decimal ApplyDiscount(decimal price) => price * 0.9m;
コードの中のメモには // を使います。/// のコメントは型や公開メンバーに付けます。IDEは呼び出しにカーソルを合わせたときにそれを表示し、コンパイラはドキュメントツールのためにXMLファイルへ書き出すこともできます。
dotnetでプロジェクトを作成して実行する
自分のマシンでは、dotnet.microsoft.comから.NET SDKをインストールしてから、次のようにします。
dotnet new console -o HelloApp
cd HelloApp
dotnet run
Hello, World!
dotnet new console は2つのファイルを作ります。HelloApp.csproj(プロジェクトファイル:ターゲットフレームワーク、設定、パッケージ参照)と Program.cs です。dotnet run はプロジェクトをコンパイルして実行します。dotnet build は実行せずにコンパイルし、出力を bin/Debug/net8.0/ に書き込みます(フォルダー名はターゲットフレームワークに従います)。
トップレベルステートメント(C# 9以降)
生成された Program.cs を開くと、これだけが書かれています。
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
これはC# 9の機能であるトップレベルステートメントのプログラムです。コンパイラが、文の周りに Program クラスと Main メソッドを生成します。using System; もありませんが、これは.NET 6以降のプロジェクトで暗黙的なusingが有効になっているからです。System、System.IO、System.Linq、System.Collections.Generic などのよく使う名前空間が、プロジェクト全体にインポートされています。
トップレベルのプログラムでも、args を読み、await を使い、終了コードを return できます。
// C# 9 and later: the whole Program.cs
Console.Write("Name: ");
string? name = Console.ReadLine();
Console.WriteLine($"Hello, {name}! You passed {args.Length} arguments.");
return 0;
トップレベルステートメントを書けるのはプロジェクトごとに1つのファイルだけで、型(クラス、レコード)はそれらの後に置かなければなりません。string? の注釈はnull許容参照型(C# 8)で、ReadLine が null を返しうるので付いています。このページの例で使っている明示的な class Program の形は同等で、古いコードやほとんどのUnityのスクリプトで目にするものなので、両方を読めるようにしておく価値があります。新しいプロジェクトで明示的な形を使いたいなら、dotnet new console に --use-program-main を渡します。
最初に目にするエラー
- CS1002: ; expected。 文のセミコロンが抜けています。エラーは、セミコロンが抜けている行の末尾で報告されます。
- CS0103: The name 'console' does not exist in the current context。 大文字と小文字の間違いか、暗黙的なusingのないプロジェクトで
using System;が抜けています。 - CS5001: Program does not contain a static 'Main' method suitable for an entry point。
Mainの綴りが間違っているか、staticでないか、サポートされていないシグネチャです。 - CS0017: Program has more than one entry point defined。 2つのクラスがそれぞれ
Mainを持っています。1つだけ残すか、.csprojのStartupObjectの設定で1つを選びます。 - ウィンドウがすぐに閉じる。 コンソールアプリをダブルクリックで起動すると、
Mainが戻った時点でウィンドウが閉じます。ターミナルから実行するか、テスト中は最後にConsole.ReadKey();を追加します。
よくある質問
C#でHello Worldはどう書きますか?
ファイルの先頭に using System; を書き、クラスの static void Main() メソッドの中に Console.WriteLine("Hello, World!"); を置きます。.NET 6以降で dotnet new console によって作ったプロジェクトなら、トップレベルステートメントがクラスと Main を生成してくれるので、ファイル全体がその1行だけで済みます。
C#のMainメソッドとは何ですか?
Main はエントリポイント、つまりプログラムの開始時にランタイムが呼び出すメソッドです。static でなければならず、void か int(終了コード)を返せ、コマンドライン引数を受け取る string[] args 引数を持てます。プログラムにはちょうど1つ必要です。
Console.WriteとConsole.WriteLineの違いは何ですか?
Console.WriteLine はテキストの後に改行を書くので、次の出力は新しい行から始まります。Console.Write はテキストだけを書くので、次の出力は同じ行に続きます。引数なしの Console.WriteLine() は空の行を出力します。
C#でユーザーの入力を読むには?
Console.ReadLine() はテキストを1行読み、それを(改行なしの)string として返し、入力がもうなければ null を返します。数値を得るには文字列を変換します。int.TryParse(Console.ReadLine(), out int n) は、テキストが数値でないときにクラッシュせず false を返します。
コマンドラインからC#のプログラムを実行するには?
.NET SDKをインストールし、dotnet new console -o HelloApp でプロジェクトを作り、cd HelloApp として、dotnet run でビルドして実行します。dotnet build はコンパイルだけを行い、出力を bin/Debug/net8.0/(またはターゲットのバージョンのフォルダー)に置きます。