C#中const与readonly的区别:何时使用静态常量
在C#中,const和readonly常用于声明不会改变的值。核心区别在于:const必须在声明时确定值,属于编译期常量且隐含静态;readonly可在构造期间修改,支持运行期动态计算。若需全局访问的运行期常量,应使用static readonly。
const:编译期静态常量
const关键字定义的变量被称为编译期常量(compile-time constant)。它的值必须在编写代码时就明确已知,编译器会将该值直接硬编码进生成的程序集(IL代码)中。
- 赋值限制:只能在变量声明的同时进行初始化,严禁在构造函数中赋值。
- 访问方式:默认具有静态属性,通常通过
类名.字段名进行访问。 - 版本依赖风险:由于值被写入调用方的IL代码中,若修改了
const的定义但未重新编译调用的程序集,引用方仍会使用旧值。这在库开发中容易导致隐蔽的错误。 - 支持的类型:仅限基本数据类型、枚举类型和字符串类型。
public class Test
{
// 正确:声明时立即赋值
public const int DefaultValue = 10;
public Test()
{
// 错误:不能在构造函数中为 const 赋值
// DefaultValue = 100;
}
} 在使用时,可以直接通过 Test.DefaultValue 引用该值。
readonly:运行期可变实例字段
readonly关键字修饰的字段称为只读字段。它在语义上比const更灵活,允许在对象的生命周期中完成一次赋值操作。
- 赋值限制:可以在声明时赋值,也可以在类的非静态构造函数中赋值。一旦赋值完成,运行时任何后续尝试修改其值的操作都会报错。
- 访问方式:属于实例成员,必须通过对象实例(如
对象.字段名)来访问。 - 动态特性:因为是运行期绑定,它可以包含通过运算得到的值,甚至支持自定义类型的封装。
public class Test
{
// 仅声明,未赋值
public readonly int RdValue;
public Test()
{
// 在构造函数中赋值
this.RdValue = 100;
}
// 尝试在普通方法或属性中修改会报错
public int InvalidProperty
{
get { return RdValue; }
set { RdValue = value; } // Error
}
}
class Program
{
static void Main(string[] args)
{
var test = new Test();
// 必须通过实例访问
Console.WriteLine(test.RdValue);
}
}扩展:Static Readonly组合
如果需要在保持“只读”特性的同时实现“静态”访问(即无需实例化即可调用),可以将两者结合使用。
- 访问路径:通过
类名.字段名直接访问。 - 赋值限制:虽然变成了静态成员,但仍受readonly规则限制——要么在声明时赋值,要么在静态构造函数中赋值。普通的实例构造函数不能再修改它。
class Program
{
static void Main(string[] args)
{
// 不需要实例化,直接通过类名访问
Console.WriteLine(Test.StaticRdValue);
}
}
public class Test
{
// 声明时赋值
public static readonly int StaticRdValue = 100;
}注意,这里提到的“变成编译期变量”说法并不准确。static readonly依然是**运行期变量**。虽然在简单数值情况下看起来很像常量,但由于它仍然涉及JIT编译时的加载过程,且在CLR内部作为对象头的一部分维护,它与const有着本质的运行时开销和版本控制区别。
核心区别总结
| 特性 | const | readonly | static readonly |
|---|---|---|---|
| 赋值时机 | 仅能在声明处 | 声明处或实例构造函数 | 声明处或静态构造函数 |
| 运行阶段 | 编译期常量 | 运行期变量 | 运行期变量 |
| 可计算性 | 不支持运行期运算 | 支持(如在构造函数内赋值) | 支持(如在静态构造函数内赋值) |
| 访问方式 | 类名.字段名 | 对象.字段名 | 类名.字段名 |
在选择使用时,如果值是固定的文本、数字且所有模块共享,优先选const;如果需要传递用户配置或基于逻辑计算得出的恒定值,请使用static readonly以保证安全性和灵活性。
以上就是C#中const与readonly的详细对比与用法介绍,更多关于C#基础知识的应用资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









