2018年4月8日のJohnDemetriouの記事「C#7.2 –読み取り専用構造体について話そう」からの翻訳1
この記事では、C#7.2以降に登場した機能について説明しますreadonly struct
。
どの構造にも、パブリック属性、プライベート属性アクセサーなどを含めることができます。次の構造例から説明を始めましょう。
public struct Person
{
public string Name {
get; set; }
public string Surname {
get; set; }
public int Age {
get; set; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
public void Replace(Person other)
{
this = other;
}
}
ご覧のとおり、すべてのプロパティは一般公開でアクセスおよび変更できます。さらに悪いことに、this
(Replace
メソッドを呼び出すことによって)アクセスして、同じ構造タイプの別のインスタンスに変更することもできます。
これがreadonly
キーワードが表示される理由です。*(のみ)*の場合、以下に示すように、構造の定義に追加します。
public readonly struct Person
{
public string Name {
get; set; }
public string Surname {
get; set; }
public int Age {
get; set; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
public void Replace(Person other)
{
this = other;
}
}
コンパイラは、以下のスクリーンショットに示すようにエラーメッセージを表示します。
なんでこんなことが起こっているの?これは、構造に定義されたreadonly
キーワードを追加すると、実際には、各属性がthis
値を含めて読み取り専用に設定されるためです。
コードをコンパイルする唯一の方法は、すべてを読み取り専用にすることです。つまり、構造は次のようになります。
public readonly struct Person
{
public string Name {
get; }
public string Surname {
get; }
public int Age {
get; }
public Person(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
}
したがって、readonly
事故の可能性のある構造例の内部または外部で追加を排除したり、割り当てられた値を変更したりすることができます。ただし、次のように、パラメーターなしのコンストラクターを頻繁に使用してプロパティに値を割り当てる場合は、次の点に注意してください。
Person s = new Person();
//错误
s.Age = 15;
s.Name = "asd";
s.Surname = "qwe";
またはこのように:
//错误
Person s = new Person
{
Age = 15,
Name = "asd",
Surname = "qwe"
};
この構造体のデフォルトのパラメーターなしコンストラクターは引き続き呼び出すことができますが、属性が読み取り専用であるため、任意の属性に値を割り当てるとコンパイルエラーが発生します。
実際、この構造体のパラメーターなしのコンストラクターを呼び出すと、そのすべてのプロパティがデフォルト値に設定され、構造体インスタンスのライフサイクル全体で変更されることはありません。
正しい初期化メソッドは、パラメーター化されたコンストラクターを呼び出すことです。
Person s = new Person("asd", "qwe", 15);
つまり、この構造を最初から不変で変更できないように定義できるため、意図を表現しやすくなります。
翻訳者のまとめ
使用readonly
修飾子宣言struct
の目的は、明示的に不変の値型を宣言することです。
readonly
構造体のすべてのデータメンバーは読み取り専用である必要があります。
- すべてのフィールドにはステートメント
readonly
修飾子が必要です - すべてのプロパティ(自動実装されたプロパティを含む)は読み取り専用である必要があります
これによりreadonly
、構造体のメンバーが構造体の状態を変更しないことが保証されます。C#8.0以降のバージョンでは、コンストラクターのメンバーの他の例に加えて、に暗黙的に含まreadonly
れています。
著者:John Demetriou
翻訳者:Technical Zemin
発行者:Technical Verses
リンク:英語テキスト