readonly
キーワードは、次の 5 つのコンテキストで使用できる修飾子です。
フィールド宣言では、
readonly
は、フィールドへの割り当てが宣言の一部として、または同じクラス内のコンストラクター内でのみ行われることを示します。 読み取り専用フィールドは、フィールド宣言とコンストラクター内で複数回割り当ておよび再割り当てできます。コンストラクターが終了した後、
readonly
フィールドを割り当てることはできません。 このルールは、値型と参照型に対して異なる影響を与えるものです。- 値型にはデータが直接含まれているため、
readonly
値型のフィールドは変更できません。 - 参照型にはデータへの参照が含まれているため、
readonly
参照型のフィールドは常に同じオブジェクトを参照する必要があります。 そのオブジェクトは変更できない可能性があります。readonly
修飾子を使用すると、フィールド値を参照型の別のインスタンスに置き換えなくなります。 ただし、この修飾子では、フィールドのインスタンス データが読み取り専用フィールドによって変更されるのを防ぐことはありません。
Warnung
変更可能な参照型である外部から参照可能な読み取り専用フィールドを含む外部から参照可能な型は、セキュリティの脆弱性である可能性があり、"読み取り専用の変更可能な参照型を宣言しないでください" という警告 CA2104 がトリガーされる可能性があります。
- 値型にはデータが直接含まれているため、
readonly struct
型定義では、readonly
は構造体の型が不変であることを示します。 詳細については、readonly
に関する記事の「構造体」セクションを参照してください。構造体型内のインスタンス メンバー宣言では、
readonly
は、インスタンス メンバーが構造体の状態を変更しないことを示します。 詳細については、「readonly
」の記事の「 インスタンス メンバー」セクションを参照してください。ref readonly
メソッドの戻り値では、readonly
修飾子は、メソッドが参照を返し、その参照への書き込みが許可されていないことを示します。-
ref readonly
パラメーターをメソッドに宣言する。
-
読み取り専用フィールドの例
この例では、クラス コンストラクターに値が割り当てられている場合でも、 year
フィールドの値をメソッド ChangeYear
で変更することはできません。
class Age
{
private readonly int _year;
Age(int year)
{
_year = year;
}
void ChangeYear()
{
//_year = 1967; // Compile error if uncommented.
}
}
readonly
フィールドには、次のコンテキストでのみ値を割り当てることができます。
宣言で変数が初期化されると、次のようになります。
public readonly int y = 5;
インスタンス フィールド宣言を含むクラスのインスタンス コンストラクター内。
静的フィールド宣言を含むクラスの静的コンストラクター内。
これらのコンストラクター コンテキストは、 readonly
フィールドを out または ref パラメーターとして渡すことが有効な唯一のコンテキストでもあります。
注
readonly
キーワードは const キーワードとは異なります。
const
フィールドは、フィールドの宣言でのみ初期化できます。
readonly
フィールドは、フィールド宣言と任意のコンストラクターで複数回割り当てることができます。 したがって、 readonly
フィールドは、使用されるコンストラクターに応じて異なる値を持つことができます。 また、 const
フィールドはコンパイル時定数ですが、次の例のように、 readonly
フィールドを実行時定数に使用できます。
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
public class SamplePoint
{
public int x;
// Initialize a readonly field
public readonly int y = 25;
public readonly int z;
public SamplePoint()
{
// Initialize a readonly instance field
z = 24;
}
public SamplePoint(int p1, int p2, int p3)
{
x = p1;
y = p2;
z = p3;
}
public static void Main()
{
SamplePoint p1 = new SamplePoint(11, 21, 32); // OK
Console.WriteLine($"p1: x={p1.x}, y={p1.y}, z={p1.z}");
SamplePoint p2 = new SamplePoint();
p2.x = 55; // OK
Console.WriteLine($"p2: x={p2.x}, y={p2.y}, z={p2.z}");
}
/*
Output:
p1: x=11, y=21, z=32
p2: x=55, y=25, z=24
*/
}
前の例では、次の例のようなステートメントを使用する場合は、次のようになります。
p2.y = 66; // Error
コンパイラ エラー メッセージが表示されます。
読み取り専用フィールドを割り当てることはできません (コンストラクターまたは変数初期化子を除く)
読み取り専用インスタンス メンバー
readonly
修飾子を使って、インスタンス メンバーで構造体の状態を変更しないことを宣言することもできます。
public readonly double Sum()
{
return X + Y;
}
注
読み取り/書き込みプロパティの場合は、readonly
アクセサーにget
修飾子を追加できます。 一部の get
アクセサーは、単にプライベート フィールドの値を返すのではなく、計算を実行して結果をキャッシュできます。
readonly
修飾子を get
アクセサーに追加することで、get
アクセサーが結果をキャッシュすることによってオブジェクトの内部状態を変更しないことが保証されます。
その他の例については、readonly
に関する記事の「 インスタンス メンバー」セクションを参照してください。
参照読み取り時の戻り値の例
readonly
のref return
修飾子は、返された参照を変更できないことを示します。 次の例では、原点への参照を返します。 呼び出し元が配信元を変更できないことを示すために、 readonly
修飾子を使用します。
private static readonly SamplePoint s_origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref s_origin;
返される型は、 readonly struct
である必要はありません。
ref
によって返すことができる任意の型は、ref readonly
から返すことができます。
readonly ref readonly 戻り値の例
ref readonly return
は、readonly
型のインスタンスメンバーstruct
に対しても使用することができます。
public struct ReadonlyRefReadonlyExample
{
private int _data;
public readonly ref readonly int ReadonlyRefReadonly(ref int reference)
{
// _data = 1; // Compile error if uncommented.
return ref reference;
}
}
このメソッドは、基本的に readonly
参照を、 readonly
されているインスタンス メンバー (この場合はメソッド) と共に返します (インスタンス フィールドを変更できません)。
C# 言語仕様
詳細については、C# 言語仕様のを参照してください。 言語仕様は、C# の構文と使用法の決定的なソースです。
言語仕様の提案を確認することもできます。
こちらも参照ください
.NET