「C# 10」の新機能で、コーダーにうれしいこと8選:.NET 6移行入門(2)
.NET 6の現状を把握し、具体的な移行方法を学ぶ連載。今回は、C# 10の新機能について。
.NET 6の現状を把握し、具体的な移行方法を学ぶ本連載「.NET 6移行入門」。第2回は、C# 10の新機能の中から注目の機能をピックアップして紹介します。
C# 10の新機能の特長は、「簡潔なコードを書くための機能」が多く追加されていることです。新しい機能を利用することで冗長な構文のコードを排除でき、簡潔で直感的なコードを記述できます。
レコード構造体
C# 9で「レコードクラス」が追加されましたが、C# 10では「レコード構造体」が追加されました。メンバーの数が少ない軽量オブジェクトの場合にクラスよりも速度が出る構造体のレコードを利用できます。
導入の意図
レコード型(レコード構造体、レコードクラス)は、簡潔なコードで便利にデータを格納するための型です。通常のクラスや構造体でデータモデルを作成しようとすると、データとしての等価性をサポートする「Equals」のオーバーライドや「operator ==」のオーバーロード、表示用の書式設定の「ToString」のオーバーライドやデータを不変にする構文などを記述する面倒な手間が生じます。
レコード型を利用すると、不変なプロパティを持つ型を簡潔な構文で作成できます。また、上記のようなデータ指向の型に役立つ動作が組み込みでサポートされているので、データモデルを簡潔に定義できます。
値の等価性
レコード構造体(レコードクラスも含む)は等価性に特徴があります。
- record class型の場合、型が同じで、同じ値が格納されていれば、2つのオブジェクトは等しい
- record struct型の場合、型が同じで、同じ値が格納されていれば、2つのオブジェクトは等しい
比較として、レコード型ではないクラスや構造体の等価性は下記の通りです。
- class型の場合、メモリ内の同じオブジェクトを参照していれば、2つのオブジェクトは等しい
- struct型の場合、型が同じで同じ値が格納されていれば、2つのオブジェクトは等しい
// レコード構造体 PersonStruct person01 = new("太郎", "山田", new DateOnly(1990, 4, 15)); PersonStruct person02 = new("太郎", "山田", new DateOnly(1990, 4, 15)); Console.WriteLine("レコード構造体"); Console.WriteLine(person01 == person02); // レコードクラス PersonClass person03 = new("太郎", "山田", new DateOnly(1990, 4, 15)); PersonClass person04 = new("太郎", "山田", new DateOnly(1990, 4, 15)); Console.WriteLine("レコードクラス"); Console.WriteLine(person03 == person04); record struct PersonStruct(string FirstName, string LastName, DateOnly Birthday); record class PersonClass(string FirstName, string LastName, DateOnly Birthday);
レコード構造体 True ----------- レコードクラス True
表示用の組み込みの書式設定
レコード型ではToStringメソッドで、パブリックプロパティとフィールドの名前と値が表示されます。データでは値を確認する機会が多いので、この機能はとても便利です。
<record type name> { <property name> = <value>, <property name> = <value>, ...}
PersonStruct person01 = new("太郎", "山田", new DateOnly(1990, 4, 15)); Console.WriteLine(person01); record struct PersonStruct(string FirstName, string LastName, DateOnly Birthday);
PersonStruct { FirstName = 太郎, LastName = 山田, Birthday = 4/15/1990 }
with式
「with式」を使うと、元のインスタンスの値はそのままに、指定したプロパティとフィールドが変更されたコピーを作成できます。膨大なプロパティを持つレコード型の一部のプロパティだけを変更したコピーを簡潔な構文で作成できるので非常に便利です。
補足ですが、C# 10以降ではレコード型ではない、struct型もwith式をサポートします。
PersonStruct person01 = new("太郎", "山田", new DateOnly(1990, 4, 15)); PersonStruct person02 = new("太郎", "山田", new DateOnly(1990, 4, 15)); person02 = person01 with { FirstName = "花子" }; Console.WriteLine(person02); Console.WriteLine(person01 == person02); record struct PersonStruct(string FirstName, string LastName, DateOnly Birthday);
PersonStruct { FirstName = 花子, LastName = 山田, Birthday = 4/15/1990 } False
なお、レコード構造体はC# 9のクラスベースのレコードと似ていますが、下記の違いがあります。
- レコード構造体のプロパティは、デフォルトで変更可能(get/set)
- レコードクラスのプロパティは、デフォルトでは不変(get/init)
※初期化後にinitキーワードが設定されているプロパティを再割り当てしようとすると、コンパイルエラーが発生します。
※readonlyキーワードを追加することで、レコード構造体を不変にできます。
レコード構造体はレコードクラスに取って代わるものではなく、レコードクラスからレコード構造体への移行を推奨するものではありません。そのため、クラスと構造体のどちらのレコードを使用するかは、メンバーの数やインスタンスが作成される回数などを考慮し、利用シナリオに合わせて選択する必要があります。
公式情報
global using
任意のソースファイルに「global using」ディレクティブを追加するか、プロジェクトファイル(*.csproj)に「Using Item」を追加することで、全てのソースファイルで使用したい名前空間を、各ソースファイルで宣言されているかのように指定することができます。
なお、static修飾子やエイリアスと一緒に使うことができます。
導入の意図
共通のusing宣言を1カ所に集約できるので、多くのusing行が不要になり、ソースコードからロジック以外の要素を排除できます。ひと言で言えば「ソースコードを簡潔にする機能」です。
global using System.Linq; global using static System.Console; // static 併用 global using E = System.Environment; // エイリアス併用
<ItemGroup> <Using Include="System.Linq" /> <Using Include="System.Console" Static="True" /> <Using Include="System.Environment" Alias="E" /> </ItemGroup>
公式情報
暗黙的なusingディレクティブ
コンパイラによって、プロジェクトの種類ごとにあらかじめ決められた、よく使われる名前空間のセットが自動的に追加されます。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- .NETとXamarinの統合、クラウドネイティブ対応はどうなるのか――2021年11月ローンチ、.NET 6の最新情報
既存の.NET Frameworkアプリの.NET 5への移行に関する考慮事項やレガシーアプリのモダナイゼーションについて解説する連載。最終回は、2021年11月ローンチ予定の.NET 6の最新情報について、Microsoft Build 2021の主な発表からお伝えする。 - Microsoft、「Visual Studio 2022 Preview 1」を公開
Microsoftは、次期「Visual Studio」の最初のプレビュー版「Visual Studio 2022 Preview 1」を公開した。メインプロセスが64bit化されており、メモリ不足に陥ることなく、極めて大規模で複雑なソリューションを扱うことが可能だ。 - 「Windows 11 on ARM」の新ABIをMicrosoftが発表、既存アプリの移植が容易に
Microsoftは、Windows 11 on ARMの新ABI「ARM64EC」を発表した。ARM64ECを利用すると、ARMをサポートしていない依存関係やプラグインを含むアプリケーションも、ARM上で動作させることができ、ネイティブARMアプリへと徐々に移行できる。