2026/4/18 10:31:44
网站建设
项目流程
绵阳网站建设100jv,饰品网站建设策划书,wordpress 新建导航,做组织架构图的网站在 C# 编程中#xff0c;const 与 readonly 经常被统称为“常量”#xff0c;但二者在初始化规则、编译/运行时行为、IL 生成方式、版本兼容性、引用类型语义等方面存在本质差异。误用不仅可能引入隐蔽的逻辑错误#xff0c;还会带来库升级后的版本陷阱。 一、初始化位置const与readonly经常被统称为“常量”但二者在初始化规则、编译/运行时行为、IL 生成方式、版本兼容性、引用类型语义等方面存在本质差异。误用不仅可能引入隐蔽的逻辑错误还会带来库升级后的版本陷阱。一、初始化位置编译时强约束 vs 运行时一次性赋值1️⃣const必须声明即赋值编译期确定必须在声明处赋值值在编译阶段就已确定任何位置都不能再次赋值包括构造函数public class ConstantDemo { public const int MaxRetryCount 3; public const string DefaultTitle C#常量解析; // ❌ 编译错误声明时未赋值 // public const double Pi; // ❌ 编译错误不能在构造函数中修改 // public ConstantDemo() // { // MaxRetryCount 5; // } }结论const是“声明即终值”的编译期常量。2️⃣readonly声明时或构造函数中赋值运行期确定可以在声明处赋值也可以在实例构造函数 / 静态构造函数中赋值每个字段只允许赋值一次public class ReadonlyDemo { // 声明时赋值 public readonly int MinAge 18; // 构造函数中赋值 public readonly int UserId; public ReadonlyDemo(int userId) { UserId userId; } // 静态 readonly在静态构造函数中赋值 public static readonly string Version; static ReadonlyDemo() { Version 1.0.1; } }结论readonly是“构造期冻结”的运行时常量。二、修饰对象范围字段 局部变量 vs 仅字段const字段 局部变量都支持public class ConstScopeDemo { public const int GlobalConst 100; public void LocalConstDemo() { const string LocalMsg 局部常量; Console.WriteLine(LocalMsg); } }readonly只能修饰字段public class ReadonlyScopeDemo { public readonly int FieldReadonly 50; public void LocalReadonlyError() { // ❌ 编译错误readonly 不能修饰局部变量 // readonly int x 10; } }三、编译期 vs 运行期这是最本质的差异 ⭐⭐⭐1️⃣const值被直接“内联”到 IL 中public const int ConstValue 10; public void UseConst() { int a ConstValue; }IL 行为本质ldc.i4.s 10 // 直接压栈常量 10⚠️重大隐患版本陷阱修改类库中的const值但引用方未重新编译引用方仍然使用旧值 ❌2️⃣readonly始终通过字段访问运行期绑定public readonly int ReadonlyValue; public ReadonlyDemo() { ReadonlyValue 20; } public void UseReadonly() { int b ReadonlyValue; }IL 行为本质ldfld int32 ReadonlyValue✅ 修改值后只需重新编译类库即可调用方无需重新编译。四、静态语义隐式静态 vs 显式静态const天然 static且禁止显式声明public class ConstStaticDemo { public const int ConstStatic 10; // ❌ 编译错误 // public static const int Invalid 20; }调用方式int x ConstStaticDemo.ConstStatic;readonly默认实例级静态需显式声明public class ReadonlyStaticDemo { public readonly int InstanceReadonly 100; public static readonly int StaticReadonly 200; }五、引用类型语义值不可变 vs 引用不可变const仅支持string/nullpublic class ConstReferenceDemo { public const string ConstString Hello; public const object ConstNull null; // ❌ 编译错误 // public const Listint ConstList new Listint(); }原因const需要编译期确定值除string外引用对象无法编译期确定readonly支持任意引用类型但仅锁引用public class ReadonlyReferenceDemo { public readonly Listint Numbers new() { 1, 2, 3 }; public void Modify() { Numbers.Add(4); // ✅ 合法 // ❌ 编译错误不能重新赋值 // Numbers new Listint(); } }⚠️readonly≠ 不可变对象锁的是引用地址不是对象内容六、完整对比速查表维度constreadonly初始化时机编译期运行期赋值位置仅声明处声明 / 构造函数修饰对象字段 局部变量仅字段静态特性默认 static默认实例级IL 行为内联常量字段访问引用类型string / null任意引用类型版本安全❌ 易出问题✅ 安全七、工程化使用建议非常重要✅ 优先使用const的场景数学常量PI、E永不变化的协议值、枚举值不会被类库外部依赖引用的内部常量public const int MaxDays 7;✅ 推荐使用readonly的场景真实项目更常见类库对外暴露的“常量”配置读取、构造参数注入引用类型常量集合、策略对象等public static readonly string ConnectionString; static DbConfig() { ConnectionString LoadFromConfig(); }八、一句话记忆法面试 实战const是“编译期写死的字面量”readonly是“构造期冻结的字段”结语const与readonly的差异本质并不在“能不能改”而在于值是在什么时候决定的编译期 vs 运行期是否参与 IL 内联是否影响程序集版本兼容在真实工程中99% 对外暴露的“常量”都应该使用readonly而不是const。理解这一点你就已经超过了大多数只停留在语法层面的 C# 开发者。