.NET 6の現状を把握し、具体的な移行方法を学ぶ連載。今回は、C# 10の新機能について。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
.NET 6の現状を把握し、具体的な移行方法を学ぶ本連載「.NET 6移行入門」。第2回は、C# 10の新機能の中から注目の機能をピックアップして紹介します。
C# 10の新機能の特長は、「簡潔なコードを書くための機能」が多く追加されていることです。新しい機能を利用することで冗長な構文のコードを排除でき、簡潔で直感的なコードを記述できます。
C# 9で「レコードクラス」が追加されましたが、C# 10では「レコード構造体」が追加されました。メンバーの数が少ない軽量オブジェクトの場合にクラスよりも速度が出る構造体のレコードを利用できます。
レコード型(レコード構造体、レコードクラス)は、簡潔なコードで便利にデータを格納するための型です。通常のクラスや構造体でデータモデルを作成しようとすると、データとしての等価性をサポートする「Equals」のオーバーライドや「operator ==」のオーバーロード、表示用の書式設定の「ToString」のオーバーライドやデータを不変にする構文などを記述する面倒な手間が生じます。
レコード型を利用すると、不変なプロパティを持つ型を簡潔な構文で作成できます。また、上記のようなデータ指向の型に役立つ動作が組み込みでサポートされているので、データモデルを簡潔に定義できます。
レコード構造体(レコードクラスも含む)は等価性に特徴があります。
比較として、レコード型ではないクラスや構造体の等価性は下記の通りです。
// レコード構造体 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式」を使うと、元のインスタンスの値はそのままに、指定したプロパティとフィールドが変更されたコピーを作成できます。膨大なプロパティを持つレコード型の一部のプロパティだけを変更したコピーを簡潔な構文で作成できるので非常に便利です。
補足ですが、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のクラスベースのレコードと似ていますが、下記の違いがあります。
※初期化後にinitキーワードが設定されているプロパティを再割り当てしようとすると、コンパイルエラーが発生します。
※readonlyキーワードを追加することで、レコード構造体を不変にできます。
レコード構造体はレコードクラスに取って代わるものではなく、レコードクラスからレコード構造体への移行を推奨するものではありません。そのため、クラスと構造体のどちらのレコードを使用するかは、メンバーの数やインスタンスが作成される回数などを考慮し、利用シナリオに合わせて選択する必要があります。
任意のソースファイルに「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>
コンパイラによって、プロジェクトの種類ごとにあらかじめ決められた、よく使われる名前空間のセットが自動的に追加されます。
Copyright © ITmedia, Inc. All Rights Reserved.