正确用法
- 只读字段:在实例化期间部分确定的字段。
public class Person {
public readonly string Name = "张三"; // 只读字段,可以在定义时或构造函数中赋值
public readonly int Age; // 只读字段,必须在构造函数中赋值
public Person(int age) {
this.Age = age;
}
}
- 只读属性:在实例化期间不变的属性。
public class Circle {
private readonly double radius; // 只读字段
public Circle(double radius) {
this.radius = radius;
}
public double Area {
get { return Math.PI * this.radius * this.raduis; } // 只读属性,计算圆的面积,无法修改
}
}
错误用法
- 静态
readonly
字段不能被设置为实例成员
public class WrongPerson {
public readonly static string Name; // 错误使用,静态字段
public WrongPerson(string name) {
this.Name = name; // 编译错误,静态字段不能被实例调用初始化
}
}
-
将只读字段或属性与
const
混淆。Readonly
和const
是不同的:const
值将在编译时设置,并且不能更改。readonly
是运行时常量,在对象实例化后设置,并且只能通过构造函数进行设置。
public class WrongCircle {
private readonly double radius = 5.0; // 错误使用,readonly不到seconds初始化
public const double PI = 3.14; // 错误使用,混淆了 const 和 readonly
public double Area {
get { return PI * this.radius * this.raduis; } // 只读属性,计算圆的面积,无法修改
}
}
使用 const
定义常量 可以使用 const 关键字定义在编译时即已知并且不能更改的值。常量必须在声明时分配初始值,因为其值在编译时就会被确定,并且无法在程序运行期间更改它的值。
public class Circle {
public const double PI = 3.1415926; // 常量字段
public double CalculateArea(double radius) {
return PI * radius * radius;
}
}
在上面的例子中,我们定义了名为 PI 的常量,在实例化 Circle 类之前都能够读取其值,而它的值是不可更改的。然后,我们写一个方法来计算圆形区域,并使用 PI 常量作为系数。
访问常量 访问常量很简单,只需要使用类名称或该字段所在实例的变量名称来引用它即可。这个常量是所有实例都共享的。
double area = Circle.PI * radius * radius;
由于常量是在编译时就已经确定其值,因此对它们进行的任何操作(例如加法、减法等)均会在编译时执行,并存储结果,并不会浪费运行时间。
const 关键字用于定义运行时恒定不变的值,对于不变或可预测的常量,使用 const 比其他方式更合适,例如用配置文件和数据库等运行期间即可读取数据的方法无法在编译时就对其进行验证。
总结:在正确使用 readonly
的情况下(例如声明为实例字段或属性),它是一个非常有用的关键字,用于指定在运行时不可更改某些值。然而,在错误使用的情况下,可能导致编译错误,或者无法达到预期的结果。
额外:
const
和 readonly
都可以用来定义常量,但是它们有以下的不同点:
相同点:
- 它们都可以用于定义只读字段或变量。
- 它们都需要在声明时进行初始化。
不同点:
const
的值必须在编译时就确定,并且不能修改;而readonly
的值可以在运行时根据需要进行分配和更改,但只能在构造函数中分配一次。const
只能用于基元数据类型(如int
、float
),枚举类型或字符串类型;而readonly
可以用于其他复杂的数据类型(如类、结构体、对象等)。const
变量在定义时被直接插入到代码中,并且不占用内存空间;而readonly
变量会在运行时被动态地分配内存空间。
重点
如果您需要定义一个编译期间永不变化的常量,请使用 const
。
而如果需要确定一个只能在运行时确定的、只读的常量,请使用 readonly
。