はじめに
C#は、去る2023年11月に.NET 8のリリースとともにバージョン12となりました。C#は、.NETの標準プログラミング言語として絶え間ない進化を続けており、このバージョン12にも便利で使い勝手のよい機能が多数実装されました。本連載では、このC#の最新バージョンにフォーカスし、その新機能を紹介していきます。また、最新バージョン以前の機能にも関連の深いものについて言及することで、新機能を線として理解できることも意識します。
機能 | 概要 |
---|---|
プライマリコンストラクタ | record型のみでサポートされていたプライマリコンストラクタがクラスでも利用可能に |
コレクション式 | 配列やリストなどのコレクションをより簡潔な書式で記述可能に |
ref readonly修飾子 | 左辺値を読み出し専用で関数に渡す場合の意図を明確に |
デフォルトのラムダ式引数 | ラムダ式のパラメータに既定値を定義できるように |
任意の型エイリアス | タプル型、配列型、ポインタ型などにも別名を設定可能に |
インライン配列 | struct型の固定長配列の利用が可能に |
Experimental属性 | 試験的機能を示す新しい属性を指定可能に |
インターセプタ | コンパイル時に置き換え可能なメソッドを定義可能に |
対象読者
- C#の最新バージョンの機能を把握したい方
- C#の経験者で、C#に改めて入門したい方
- プログラミング言語の最新パラダイムに関心のある方
必要な環境
本記事のサンプルコードは、以下の環境で動作を確認しています。
-
macOS Sonoma
- .NET 8 SDK(8.0.101)
サンプルの実行
掲載サンプルは、基本的にプロジェクトのProgram.csファイルに記述しています。簡略化のために、C# 9より使用可能になったトップレベルステートメントの記法を用いています。このため、クラスなどの定義がソースコードの後方に配置されます。また、.NET 8環境でのみ動作しますので、.NET 8環境を用意した上で、プロジェクトフォルダでdotnet runコマンドで実行してください。
プリミティブ型、配列、タプルなどを対象に、型エイリアスの定義が可能に!
C# 12では、タプル型、配列型、ポインタ型などにも型エイリアス(別名)を設定可能になりました。
C#では、型エイリアス(別名)の指定をusing文で行うことができましたが、対象はクラスなどの非プリミティブ型に限定されていました。つまり、C言語でいう「typedef int INT;」のような定義はできなかったわけです。無理やり定義しようとするなら、以下のように構造体に対して定義する必要がありました。
using Integer = System.Int32; using NullableInteger = System.Nullable<System.Int32>; using IntegerTuple = System.ValueTuple<System.Int32, System.Int32>; Integer i = 1; NullableInteger n1 = 2; NullableInteger n2 = null; IntegerTuple it = (3, 4);
しかしながら、ジェネリック型の型パラメータには、以下のようにプリミティブ型を直接記述することができます。
using GenericInteger = System.ValueTuple<int>; using GenericIntegerArray = System.ValueTuple<int[]>; using GenericNullableInteger = System.ValueTuple<int?>; using GenericIntegerTuple = System.ValueTuple<(int, int)>;
これができて、シンプルな型エイリアスが定義できないのは不便ですね。C# 12ではついに、プリミティブ型、配列、タプルなどを対象に型エイリアスの定義が可能になりました。特に、配列に対しては構造体を使っても型エイリアスを定義する方法はありませんでしたが、これができるようになったわけです。
using Long = long; using IntegerArray = int[]; using NullableLong = long?; using LongTuple = (long, long); Long l = 100; IntegerArray ia = [1, 2, 3]; NullableLong l1 = 200; NullableLong l2 = null; LongTuple lt = (1000, 2000);
例えばSystem.Int32は、int型のフィールドを1個だけ持つ構造体であり、コンパイラが内部的にプリミティブ型として処理します。C# 12で、型エイリアスの定義についても同様の扱いをするようになったということです。