readonly (C#-Referenz)

Das Stichwort readonly ist ein Modifizierer, der in fünf Kontexten verwendet werden kann:

  • In einer Felddeklaration gibt readonly an, dass die Zuweisung zum Feld nur als Teil der Deklaration oder in einem Konstruktor derselben Klasse erfolgen kann. Ein readonly-Feld kann innerhalb der Felddeklaration und des Konstruktors mehrmals zugewiesen und neu zugewiesen werden.

    Ein readonly-Feld kann nicht zugewiesen werden, sobald der Konstruktor vorhanden ist. Diese Regel hat verschiedene Auswirkungen auf Wert- und Verweistypen:

    • Da Werttypen ihre Daten direkt enthalten, ist ein Feld des Werttyps readonly unveränderlich.
    • Da Verweistypen einen Verweis auf ihre Daten enthalten, muss ein Feld des Verweistyps readonly immer auf das gleiche Objekt verweisen. Dieses Objekt ist möglicherweise nicht unveränderlich. Der readonly-Modifizierer verhindert, dass der Feldwert durch eine andere Instanz des Verweistyps ersetzt wird. Der Modifizierer verhindert jedoch nicht, dass die Instanzdaten des Felds durch das schreibgeschützte Feld geändert werden.

    Warnung

    Ein extern sichtbarer Typ, der ein extern sichtbares schreibgeschütztes Feld enthält, bei dem es sich um einen änderbaren Verweistyp handelt, kann ein Sicherheitsrisiko darstellen und die folgende Warnung auslösen: CA2104: „Schreibgeschützte änderbare Verweistypen nicht deklarieren.“

  • In einer readonly struct-Typdefinition weist readonly darauf hin, dass der Strukturtyp unveränderlich ist. Weitere Informationen finden Sie im Abschnitt zur readonly-Struktur des Artikels Strukturtypen.

  • In einer Instanzmemberdeklaration innerhalb eines Strukturtyps gibt readonly an, dass ein Instanzmember den Zustand einer Struktur nicht ändert. Weitere Informationen finden Sie im Abschnitt readonly-Instanzmember des Artikels Strukturtypen.

  • In einer ref readonly-Methodenrückgabe gibt der readonly-Modifizierer an, dass die Methode eine Referenz zurückgibt, und Schreibvorgänge für diese Referenz nicht zulässig sind.

Beispiel für ein readonly-Feld

In diesem Beispiel kann der Wert des Felds year nicht in der Methode ChangeYear geändert werden, obwohl ihm im Klassenkonstruktor ein Wert zugewiesen ist:

class Age
{
    private readonly int _year;
    Age(int year)
    {
        _year = year;
    }
    void ChangeYear()
    {
        //_year = 1967; // Compile error if uncommented.
    }
}

Sie können einem readonly-Feld nur in den folgenden Kontexten einen Wert zuweisen:

  • Wenn die Variable in der Deklaration initialisiert ist, z.B.:

    public readonly int y = 5;
    
  • In einem Instanzenkonstruktor der Klasse, die die Deklaration des Instanzfelds enthält.

  • Im statischen Konstruktor der Klasse, die die Deklaration des statischen Felds enthält.

Diese Konstruktorkontexte sind auch die einzigen Kontexte, in denen es zulässig ist, ein readonly-Feld als out- oder ref-Parameter zu übergeben.

Hinweis

Das Schlüsselwort readonly unterscheidet sich vom Schlüsselwort const. Ein const-Feld kann nur bei der Deklaration des Felds initialisiert werden. Ein readonly-Feld kann mehrere Male in der Felddeklaration und in einem Konstruktor zugewiesen werden. Daher können readonly-Felder abhängig vom verwendeten Konstruktor über unterschiedliche Werte verfügen. Außerdem ist ein const-Feld eine Kompilierzeitkonstante, während ein readonly-Feld wie im folgenden Beispiel für Laufzeitkonstanten verwendet werden kann:

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
    */
}

Wenn Sie im vorherigen Beispiel eine Anweisung wie die folgende verwenden:

p2.y = 66;        // Error

erhalten Sie die Compilerfehlermeldung:

Einem schreibgeschützten Feld kann nichts zugewiesen werden (außer in einem Konstruktor oder Variableninitialisierer)

Schreibgeschützte Instanzmember

Sie können auch den readonly-Modifizierer verwenden, um zu deklarieren, dass ein Instanzmember den Zustand einer Struktur nicht ändert.

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

Hinweis

Bei einer Lese-/Schreibeigenschaft können Sie der get-Zugriffsmethode den Modifizierer readonly hinzufügen. Einige get-Zugriffsmethoden können eine Berechnung durchführen und das Ergebnis zwischenspeichern, anstatt einfach den Wert eines privaten Felds zurückzugeben. Durch das Hinzufügen des Modifizierers readonly zur get-Zugriffsmethode wird sichergestellt, dass die get-Zugriffsmethode den internen Zustand des Objekts nicht ändert, indem ein Ergebnis zwischengespeichert wird.

Weitere Beispiele finden Sie im Abschnitt readonly-Instanzmember des Artikels Strukturtypen.

Rückgabebeispiel für ref readonly

Der readonly-Modifizierer für ref return gibt an, dass der zurückgegebene Verweis nicht geändert werden kann. Das folgende Beispiel gibt einen Verweis auf den Ursprung zurück. Dabei wird über den readonly-Modifizierer angegeben, dass die aufrufenden Funktionen den Ursprung nicht ändern können:

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

Der zurückgegebene Typ muss nicht readonly struct aufweisen. Jeder Typ, der von ref zurückgegeben werden kann, kann auch von ref readonly zurückgegeben werden.

Rückgabebeispiel für „readonly ref readonly“

ref readonly return kann auch mit readonly-Instanzmembern für struct-Typen verwendet werden:

public struct ReadonlyRefReadonlyExample
{
    private int _data;

    public readonly ref readonly int ReadonlyRefReadonly(ref int reference)
    {
        // _data = 1; // Compile error if uncommented.
        return ref reference;
    }
}

Die Methode gibt im Wesentlichen einen readonly-Verweis zusammen mit dem Instanzmembern zurück (in diesem Fall eine Methode), und zwar readonly (kann keine Instanzfelder ändern).

C#-Sprachspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Sehen Sie sich auch die Vorschläge zur Sprachspezifikation an:

Siehe auch