readonly (C# リファレンス)

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

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

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

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

    警告

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

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

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

  • ref readonly メソッドの戻り値では、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 インスタンスのメンバー

readonly 修飾子を使って、インスタンス メンバーで構造体の状態を変更しないことを宣言することもできます。

public readonly double Sum()
{
    return X + Y;
}

Note

読み取り/書き込みプロパティの場合は、readonly 修飾子を get アクセサーに追加できます。 一部の get アクセサーは、プライベート フィールドの値を単に返すのではなく、計算を実行して結果をキャッシュする場合があります。 readonly 修飾子を get アクセサーに追加すると、get アクセサーが結果をキャッシュすることでオブジェクトの内部状態を変更しないことが保証されます。

その他の例については、「構造体の種類」の記事の「readonly インスタンス メンバー」セクションを参照してください。

ref readonly の戻り値の例

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

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 は、struct 型の readonly インスタンス メンバーと一緒に使うこともできます。

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# の構文と使用法に関する信頼性のある情報源です。

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

関連項目