readonly
關鍵詞是可在五個內容中使用的修飾詞:
在 欄位宣告中,
readonly
表示欄位的工作分派只能當做宣告的一部分或在同一類別的建構函式中發生。 在欄位宣告和建構函式內,唯讀欄位可以多次被指派和重新指派。建構函式結束後,
readonly
欄位不能被指派。 此規則對實值類型和參考型別有不同的影響:- 因為實值型別會直接包含其數據,所以實值型別的
readonly
欄位是不可變的。 - 由於參考型別包含其數據的參考,因此,參考型別的
readonly
欄位一律必須參考相同的物件。 該物件可能不可變。readonly
修飾詞可防止以參考型別的不同實例取代域值。 不過,修飾詞不會防止欄位的實例數據被透過只讀欄位進行修改。
警告
外部可見的類型,若包含外部可見的只讀欄位,而該欄位是不可變的參考型別,可能構成安全性漏洞,並可能會觸發警告 CA2104:「請勿宣告可變的只讀參考型別」。
- 因為實值型別會直接包含其數據,所以實值型別的
readonly struct
在類型定義中,readonly
表示結構類型是不可變的。 如需詳細資訊,請參閱readonly
結構類型一文的結構一節。在結構類型內的實例成員宣告中,
readonly
表示實例成員不會修改結構的狀態。 如需詳細資訊,請參閱readonly
結構類型一文的實例成員一節。在
ref 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
修飾詞,宣告執行個體成員不會修改結構的狀態。
public readonly double Sum()
{
return X + Y;
}
備註
在讀取/寫入屬性的情況下,您可以將readonly
修飾詞新增至get
存取子。 某些 get
存取子可能會執行計算並快取結果,而不只是傳回私用字段的值。 將 readonly
修飾詞新增至 get
存取子,可確保 get
存取子不會藉由快取任何結果來修改對象的內部狀態。
Ref readonly 傳回範例
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# 語法和使用方式的最終來源。
您也可以檢視語言規格提案: