可讀(C# 參考)

在五個情境中使用此 readonly 關鍵字作為修飾語:

  • 欄位宣告中, readonly 表示你只能在宣告期間或同一類別的建構子中指派該欄位。 你可以在欄位宣告和建構子中多次指派和重新指派一個可讀欄位。

    建構器完成後你無法指派 readonly 欄位。 此規則對值類型與參考類型有不同影響:

    • 因為實值型別會直接包含其數據,所以實值型別的 readonly 欄位是不可變的。
    • 由於參考型別包含其數據的參考,因此,參考型別的 readonly 欄位一律必須參考相同的物件。 該物件可能不可變。 readonly修飾詞可防止以參考型別的不同實例取代域值。 不過,修飾詞不會防止欄位的實例數據被透過只讀欄位進行修改。

    警告

    若外部可見類型包含一個外部可見的唯讀欄位且為可變參考類型,可能是安全漏洞,並可能觸發 CA2104 警告:「請勿宣告唯讀可變參考類型。」

  • 在型別定義中 readonly struct ,表示 readonly 結構型態是不變的。 如需詳細資訊,請參閱readonly結構類型一文的結構一節。

  • 在結構型別中的實例成員宣告中, readonly 意指實例成員不會修改結構的狀態。 如需詳細資訊,請參閱readonly結構類型一文的實例成員一節。

  • 方法ref readonly回傳中,修readonly飾符表示該方法回傳了一個參考,且不允許寫入該參考。

C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。

文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。

小提示

欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。

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 欄位作為 outref 參數傳遞的有效上下文。

備註

關鍵詞 readonlyconst 關鍵詞不同。 你只能在欄位宣告時初始 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;
}

備註

對於讀寫屬性,你可以在 accessor 上加上 readonly 修飾符 get 。 有些 get 存取器會執行計算並快取結果,而非僅回傳私有欄位的值。 透過將修飾符加入readonlyget存取者,你保證get該存取器不會透過快取任何結果來修改物件的內部狀態。

更多範例請參閱readonly結構類型文章中的實例成員部分。

Ref readonly 傳回範例

a 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# 語法和使用方式的最終來源。

另請參閱