執筆者: しおかい
これは OUCC Advent Calendar 2022の7日目の記事です。 空いてたので即興で書きました。
最近の(と言っても.NET6とかまでの話ですが)C#にはいろいろ機能が追加されていまして、Hello Worldもいろいろな書き方が出来るようになっています。
dotnet new console
して出来たProgram.csに
Console.WriteLine("Hello World");
の1行しかなく、にもかかわらず実行できるのを見て戸惑った人も居るのではないでしょうか。
という事で、今回はHello Worldを短く書くための3つの機能を紹介し、最終的に上記の1行コードにしていきます。
なお以下では特記無き限りMain
は返り値void
、引数string[]
としました。
0.プレーンな書き方
最も基本的な書き方はおそらく以下のようになると思います。
using System;
namespace Plane
{
public class Sample
{
public static void Main(string[] arg)
{
Console.WriteLine("Hello World");
}
}
}
System
をusing
しConsole.WriteLine
でHello Worldしています。
特に言う事は無いでしょう。
1.ファイルスコープ名前空間
上記ではnamespaceでスコープを括っているが、ファイルスコープ名前空間という機能を使えばこの括りを外せ、インデントを1段減らすことが出来ます。
using System;
namespace Plane;
public class Sample
{
public static void Main(string[] arg)
{
Console.WriteLine("Hello World");
}
}
これは、ファイル全体が名前空間で括られているのと同じ扱いになります。
一応デメリットとして、ファイルスコープ名前空間を使うと1ファイルに1つしか名前空間を(通常の名前空間もファイルスコープ名前空間も)指定できませんが、普通1ファイルに複数名前空間を指定することは無いので問題ないでしょう。
2.ImplicitUsings
C#10からglobal using
という機能が追加されました。
これは例えば
global using System;
とすると、同じプロジェクトにある全てのファイルでusing System
しているのと同じことになります。
.NET6ではこれを利用してImplicitUsings
という機能が提供されています。
これは読んで字のごとく「暗黙的なusing」であり、いくつかの名前空間を.NETが勝手にglobal using
してくれるというものです。
コンソールアプリケーションでは
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
が自動的に行われた扱いになります。 内容はプロジェクトの種類によって異なる様です。 これを利用すると、Hello Worldは以下のようになります。
namespace Implicit;
public class Sample
{
public static void Main(string[] arg)
{
Console.WriteLine("Hello World");
}
}
using System
が無くなりました。
幾分すっきりしましたね。
3.トップレベルステートメント
C#9から、トップレベルステートメントと言って、名前空間やクラスや関数の外、トップレベルの場所に直接式(ステートメント)を書けるようになりました。 すなわち、先ほどのHello Worldは、Mainの中身だけ抜き取って以下のように書けます。
Console.WriteLine("Hello World");
これが始めに出てきた1行コードの正体です。 実際にはコンパイル時にclassとMainが自動生成されている様です。 注意点として、トップレベルステートメントより上に名前空間やクラスを定義するとエラーになります。
// これはエラー
namespace TopLevel;
Console.WriteLine("Hello World");
// これもエラー
namespace TopLevel
{
}
Console.WriteLine("Hello World");
// これもエラー
namespace TopLevel
{
Console.WriteLine("Hello World");
}
// これはセーフ
Console.WriteLine("Hello World");
namespace TopLevel
{
}
また、トップレベルステートメントを書けるのは1プロジェクトに1ファイルまでです。
なお、関数やusing
は上に定義できます。
// これはセーフ
void Hello() => Console.WriteLine("Hello World");
Hello();
この関数はプロジェクト全体から見ることが出来ますが、アクセスは出来ないようになっています。
ちなみにこのトップレベルステートメント、await
を使うと自動生成Mainは勝手にasync
になってくれます。
なので
Console.WriteLine("Hello");
await Task.Delay(5000);
Console.WriteLine("World.");
のようにTaskも使用できます。
ただし、ref
は直接使用できません。
var hoge = new[]{0, 1, 2};
// エラー
ref var e = ref hoge[^1];
e++;
Console.WriteLine(hoge[^1]);
// これはセーフ
void Hoge()
{
var hoge = new[]{0, 1, 2};
ref var e = ref hoge[^1];
e++;
Console.WriteLine(hoge[^1]);
}
Hoge();
終わりに
というわけで、C#でHello Worldを簡潔に書けるようになる機能3つを紹介しました。 決まり切ったことを省略できるのは便利で嬉しいことです。
大きく見た目の変わるトップレベルステートメントはともかく、ファイルスコープ名前空間とImplicitUsingsは便利なので使っていきたいと思います。
参考
- 【C# 10.0】ファイル スコープ名前空間 (一斉置換設定) | ++C++; // 未確認飛行 C ブログ
- 名前空間 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
- 名前空間キーワード - C# リファレンス | Microsoft Learn
- 【C# 10.0】 ImplicitUsings (自動 global using) | ++C++; // 未確認飛行 C ブログ
- C# 10.0 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
- .NET 6 以降での C# コンソール アプリ テンプレートの変更 - .NET | Microsoft Learn
- C# 9.0 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
- 【C# 10.0】 トップ レベル ステートメントの変更点 | ++C++; // 未確認飛行 C ブログ
- 最上位レベルのステートメント - C# チュートリアル | Microsoft Learn