37
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C#】 最新バージョンの主要機能まとめ — 小さなアップデートで大きく変わるコード設計

Posted at

はじめに

突然ですが、C#の新バージョン機能って追えてますか?

言語仕様はバージョンアップのたびにたくさんの新要素が増えています。ほんの数行の文法シュガーでも、コードの可読性やメンテナンス性を大きく向上させることがあったりします。

今回は、C# 10 以降(C# 11, C# 12…など)で追加された「小さいけれど便利な機能」にフォーカスしながら、具体的な使い方や注意点をまとめました。

(かなり地味だけど個人的にはすごいやつ集めてみました!)

  • 「そういえばこんな機能あったんだ…」
  • 「昔の書き方をそのまま使ってたけど、もっと簡潔にできるじゃん!」

など、新たな発見のきっかけになれば嬉しいです。

動作確認環境: .NET 7/C# 11, Visual Studio 2022
(C# 12 Preview 版の機能に関しては説明時に明示します)


1. File-scoped Namespace(C# 10)

1.1 どんな機能?

従来、C# の名前空間宣言はこんな感じでした。

C#
namespace SampleNamespace
{
    // クラスやメソッド
    public class SampleClass
    {
        // ...
    }
}

C# 10 からは “File-scoped Namespace” と呼ばれる新しい宣言が使えます。

C#
namespace SampleNamespace;

public class SampleClass
{
    // ...
}

  • 波カッコ{}が不要 で、ファイルの先頭に namespace X; の一行を書くと、同じファイル内のすべてがその名前空間に属します。
  • 小規模なプロジェクトやサンプルコードで、見た目がすっきりして読みやすくなるというメリットがあります。

1.2 ポイント

  • ファイルの先頭以外に宣言するとコンパイルエラーになるため、ファイル先頭で使うのが原則。
  • 複数のnamespaceを一つのファイルで定義したい場合は、従来の波カッコ付き宣言を併用する必要があります。

2. Global Usings(C# 10)

2.1 なにが嬉しい?

C# 10 では global using キーワードが導入され、プロジェクト全体で共通して使う名前空間をまとめて宣言できるようになりました。

C#
// GlobalUsings.cs などにまとめて
global using System;
global using System.Collections.Generic;
global using System.Threading.Tasks;

これにより、各コードファイルでいちいち using System; と書かなくてもいい ので、ボイラープレートが減ります。

2.2 ポイント

  • 大規模プロジェクトでもスッキリする反面、どこで宣言されているか分かりにくいデメリットもあるので、使いすぎには注意。
  • global using static SomeClass; のように staticクラスをグローバルスコープにインポートすることも可能。

3. 新しいパターンマッチング(C# 10, 11 以降)

3.1 List Patterns(C# 11)

C# 11 では、配列やリストに対するパターンマッチングが強化されました。たとえば、特定の要素パターンと要素数を同時にチェックする例を見てみましょう。

C#
var data = new[] { 1, 2, 3 };

if (data is [1, 2, _])
{
    Console.WriteLine("最初の2つの要素が1,2、かつ要素数3の配列ですね");
}

  • is [1,2,_] のように要素を列挙してマッチング可能
  • _ はワイルドカードで「任意の値OK」を意味

さらに、スライスパターン .. を使った高度なマッチングも書けます。

C#
if (data is [1, .. var middle, 3])
{
    Console.WriteLine($"1と3で挟まれた要素は{string.Join(",", middle)}です");
}

3.2 Required members(C# 11)

クラスや構造体のプロパティを 必須 にできる機能です。

たとえば、次のように required キーワードを指定すると、そのプロパティが インスタンス化時 に必ずセットされるよう強制します。

C#
public class Person
{
    public required string Name { get; set; }
    public int Age { get; set; }
}

// 使い方
var p = new Person
{
    Name = "John",
    Age = 30
};
// Name を指定しないとコンパイルエラーになる

データの不整合をコンパイル時に防ぐことができるため、宣言的にデザインを強化できます。


4. Raw String Literals(C# 11)

従来、文字列リテラルに特殊文字や改行を含めるには、\n\\ でエスケープする必要がありました。C# 11 以降の Raw String Literal なら、エスケープせずにそのまま書けます。

C#
var raw = """
    これは「生」の文字列です。
    ダブルクォーテーション(")もそのまま書けるし、
    \n のエスケープも必要ありません。
    """;
Console.WriteLine(raw);

  • 三重の二重引用符 """ の内部がすべてそのまま文字列として扱われる
  • JSONやSQLをそのまま埋め込むケースなどで重宝します

5. Param Null Checking(C# 12 予定)

これは C# 12 で追加が予定されている機能 (現時点では Preview) です。

メソッドの引数が null だった場合、自動的に ArgumentNullException を投げてくれるシンタックスシュガー。

C#
public void PrintMessage(string message!!)
{
    Console.WriteLine(message);
}

  • string message!! と書くだけで、if (message == null) throw new ArgumentNullException(nameof(message)); を書く手間が省ける
  • 開発者がよく書く「引数チェック」の定型文を大幅に削減することが期待されます

※ Visual Studio 2022 の Preview チャンネルや .NET 8 の Preview 版を使うと試せます


6. ちょっとした実用例

6.1 例: 入力配列の分岐処理

例えば、コマンドライン引数やユーザー入力を List Pattern でスマートに振り分けるとこんな感じです。

C#
static void HandleArgs(string[] args)
{
    switch (args)
    {
        case ["--help"]:
            ShowHelp();
            break;
        case ["--version"]:
            ShowVersion();
            break;
        case [var command, .. var options]:
            ExecuteCommand(command, options);
            break;
        default:
            Console.WriteLine("Usage: app --help | --version | <command> [options]");
            break;
    }
}

  • switch (args) として、各パターンに応じた分岐ロジックを記述
  • [var command, .. var options] で、最初の要素を command、残りを options として受け取る

6.2 例: 最小限コードでAPIを作る (global using + Minimal API)

.csproj<ImplicitUsings>enable</ImplicitUsings> と、global using を併用すると、大量の using を書かずに済みます。さらに ASP.NET Core 6/7 以降の Minimal API を使うと、Web API をわずか数行で書けるのがこちら...

C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.MapPost("/echo", (MyData data) => data);

app.Run();

record MyData(string Message);

  • HttpGetHttpPost のエンドポイントをシンプルなラムダ式で実装
  • 小規模サービスやプロトタイプでとても便利

7. まとめ

C# はバージョンが上がるごとに地味で細かい改善が積み重なっていて、ついつい見逃してしまう機能も多いです。

  • File-scoped NamespaceGlobal Usingsボイラープレートを削減
  • List PatternsRequired Members のような パターンマッチングや型システムの強化
  • Raw String Literals で文字列リテラルが扱いやすくなる
  • そして Param Null Checking (C# 12 予定) など、引数チェックの手間が減る プレビュー機能

今後も C# は進化し続けるので、新しい文法やライブラリを適切に取り入れながら、コードの可読性や保守性をどんどん上げていけたらいいなと思います。

参考リンク(出典)


おわりに

少しずつ盛りだくさんになりがちな C# の最新機能ですが、「1つでも面白そう」「使えそう」 と思ったら、ぜひプロジェクトへ試験導入してみてください!!

37
26
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?