readonly (C# リファレンス)

readonly キーワードは、次の 4 つのコンテキストで使用できる修飾子です。

  • フィールドの宣言では、readonly は、フィールドへの割り当てが、宣言の一部として、または同じクラスのコンストラクター内でのみ可能であることを示します。 readonly フィールドは、フィールドの宣言とコンストラクターで複数回割り当ておよび再割り当てを行うことができます。

    readonly フィールドは、コンストラクターが終了した後で割り当てることはできません。 この規則は、値型と参照型では意味が異なります。

    • 値型にはそのデータが直接含まれるため、readonly 値型のフィールドは変更できません。
    • 参照型にはそのデータへの参照が含まれるため、readonly 参照型のフィールドは、常に同じオブジェクトを参照する必要があります。 そのオブジェクトは不変ではありません。 readonly 修飾子があると、フィールドを参照型の別のインスタンスで置き換えることはできません。 ただし、フィールドのインスタンス データを読み取り専用フィールドで変更することは禁止されません。

    警告

    変更可能な参照型である外部から参照できる読み取り専用フィールドを含む外部から参照できる型はセキュリティの脆弱性があり、警告 CA2104 がトリガーされる可能性があります: "読み取り専用の変更可能な参照型を宣言しません"。

  • readonly struct 型定義では、readonly は構造体型が変更不可であることを示します。 詳細については、「構造体型」の記事の「readonly 構造体」セクションを参照してください。

  • 構造体型内のインスタンス メンバー宣言では、readonly は、インスタンス メンバーによって構造体の状態が変更されないことを示します。 詳細については、構造体型に関する記事の「readonly インスタンス メンバー」セクションを参照してください。

  • ref readonly メソッドの戻り値では、readonly 修飾子は、メソッドが参照を返し、その参照への書き込みが許可されないことを示します。

readonly structref readonly のコンテキストは、C# 7.2 で追加されました。 readonly 構造体メンバーは、C# 8.0 で追加されました。

読み取り専用フィールドの例

この例では、year フィールドの値は、クラス コンストラクターで値が割り当てられていても ChangeYear メソッドでは変更できません。

class Age
{
    readonly int year;
    Age(int year)
    {
        this.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

この場合、次のコンパイル エラー メッセージが表示されます。

読み取り専用フィールドに割り当てることはできません (コンストラクター、変数初期化子では可)

ref readonly の戻り値の例

ref returnでの readonly 修飾子は、返される参照を変更できないことを示します。 次の例は、origin に参照を返します。 readonly 修飾子を使用して、呼び出し元が origin を変更できないことを示しています。

private static readonly SamplePoint origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref origin;

返される型を readonly struct にする必要はありません。 ref で返すことができる任意の型を、ref readonly で返すことができます。

C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。

言語仕様の提案を参照することもできます。

関連項目