readonly (C# リファレンス)

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

  • フィールド宣言では、readonlyは、宣言中または同じクラスのコンストラクター内でのみフィールドを割り当てることができるということです。 フィールド宣言とコンストラクター内で、読み取り専用フィールドの割り当てと再割り当てを複数回行うことができます。

    コンストラクターの完了後、 readonly フィールドを割り当てることはできません。 この規則は、値型と参照型に異なる影響を与える。

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

    Warnung

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

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

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

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

C# 言語リファレンスには、C# 言語の最新リリース バージョンが記載されています。 また、今後の言語リリースのパブリック プレビューの機能に関する初期ドキュメントも含まれています。

このドキュメントでは、言語の最後の 3 つのバージョンまたは現在のパブリック プレビューで最初に導入された機能を特定します。

ヒント

C# で機能が初めて導入された時期を確認するには、 C# 言語バージョン履歴に関する記事を参照してください。

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

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

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;
}

注

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

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

参照読み取り時の戻り値の例

ref returnのreadonly修飾子は、返された参照を変更できないことを示します。 次の例では、原点への参照を返します。 呼び出し元が配信元を変更できないことを示すために、 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 戻り値の例

struct型のインスタンス メンバーreadonlyref readonly returnを使用することもできます。

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# の構文と使用法の決定的なソースです。

こちらも参照ください