在 C# 中,**只读变量(readonly)**的核心特性就是一旦初始化后,它的值在对象的生命周期内(对于实例字段)或应用程序的生命周期内(对于静态字段)都不能被修改。以下是如何保证只读变量的值不被修改的具体机制和实现方式:
1. 定义只读变量
只读变量可以通过以下两种方式赋值:
- 在声明时赋值。
- 在类的构造函数中赋值。
赋值后,它的值将不可再更改。
示例:
public class ReadonlyExample
{
public readonly int ReadonlyValue; // 实例只读字段
public static readonly string StaticReadonlyValue; // 静态只读字段
// 静态构造函数初始化静态只读字段
static ReadonlyExample()
{
StaticReadonlyValue = "Initialized in static constructor";
}
// 构造函数初始化实例只读字段
public ReadonlyExample(int value)
{
ReadonlyValue = value;
}
}
在上面的代码中:
- ReadonlyValue 只能在构造函数中被赋值。
- StaticReadonlyValue 只能在静态构造函数或声明时被赋值。
2. 编译器强制保障
编译器会确保只读字段只能在以下位置赋值:
- 声明时赋值:public readonly int ReadonlyValue = 42;
- 在构造函数或静态构造函数中赋值:public ReadonlyExample(int value) { ReadonlyValue = value; // 仅能在构造函数内赋值 }
如果试图在其他地方修改 readonly 字段的值,编译器会报错。例如:
public void UpdateReadonlyValue(int newValue)
{
ReadonlyValue = newValue; // 编译错误:Cannot assign to 'ReadonlyValue' because it is readonly
}
3. 静态只读字段的初始化
静态只读字段的值可以通过以下两种方式赋值:
- 声明时:public static readonly string StaticField = "Initialized";
- 静态构造函数:static ReadonlyExample() { StaticField = "Initialized in static constructor"; }
一旦静态只读字段的值被初始化,就不能再更改。
4. 使用只读字段的优势
- 避免不小心修改: 通过限制赋值位置(仅限构造函数或声明时),确保值的稳定性。
- 线程安全: 只读字段在初始化后不会再被修改,因此是天然的线程安全的。
- 增强代码可读性: 表示该字段是不可变的,增加了代码的可预测性。
5. 只读字段与常量的区别
虽然 readonly 字段值不能被修改,但它和 const 常量有本质区别:
- const 是编译期常量,必须在编译时指定值,值在使用处会被内联到代码中。
- readonly 的值可以在运行时通过构造函数初始化,但在初始化后不能再被修改。
6. 示例应用场景
只读字段的典型应用包括:
- 数据库连接字符串:值可能来自配置文件,在运行时初始化,但之后不允许更改。
- 应用程序的只读设置:在初始化时读取某些值并确保运行时不可变。
示例:
public class Configuration
{
public readonly string ConnectionString;
public Configuration(string connectionString)
{
ConnectionString = connectionString; // 初始化后不允许更改
}
}
总结
要保证 readonly 变量的值不被修改:
- 只能在声明时或通过构造函数初始化。
- 编译器会强制阻止在其他位置对其重新赋值。
- 静态只读字段只能在静态构造函数或声明时赋值。
这使得 readonly 成为管理运行时初始化的不可变值的理想选择。