【C#】C# 中的 `init`、`readonly` 和 `const` 有什么区别?

⚙️ C# 中的 initreadonlyconst 有什么区别?

在 C# 编程中,我们经常需要定义 不可变(immutable) 的数据。那么该用 constreadonly,还是 init 呢?这三者虽然都可用于定义不可变成员,但它们的应用场景和语法限制却大不相同。本文将通过对比和示例,帮助你理清它们的区别与用法。


📌 1. 简要对比表

特性 const readonly init
赋值时机 定义时 构造函数或定义时 初始化时(对象构造期间)
是否编译期常量 ✅ 是 ❌ 不是 ❌ 不是
可用于字段 ✅(属性)
可用于属性 ✅(支持 get-only) ✅(支持 set-only-once)
赋值位置 定义时 构造函数、字段初始化 对象初始化表达式 {}
常用于 全局常量、数学值 构造后不变的实例字段 构造后不变但支持对象初始化的属性

🧱 2. const ------ 编译期常量

csharp 复制代码
public class Constants
{
    public const double Pi = 3.14159;
}

✅ 特点:

  • 必须在定义时赋值
  • 编译为常量值,直接嵌入调用代码中
  • 只能修饰 基本类型string 等编译期常量

⚠️ 注意:

  • 修改 const 值需 重新编译所有引用它的程序集,否则可能仍然使用旧值!

🧱 3. readonly ------ 运行期常量(构造后不可变)

csharp 复制代码
public class Config
{
    public readonly string Version;

    public Config(string version)
    {
        Version = version;
    }
}

✅ 特点:

  • 可以在定义时或构造函数中赋值
  • 适合依赖运行期值(如时间戳、GUID、配置文件)
csharp 复制代码
public readonly DateTime StartTime = DateTime.Now;

⚠️ 注意:

  • readonly 不能在构造函数外被修改
  • 可用于字段,常配合 private 修饰

🧱 4. init ------ 初始化器赋值(C# 9 引入)

csharp 复制代码
public class Person
{
    public string Name { get; init; }
    public int Age { get; init; }
}

✅ 特点:

  • 支持对象初始化表达式语法 {} 中赋值
  • 一旦对象构造完成,属性就不可更改
csharp 复制代码
var p = new Person { Name = "Alice", Age = 30 };
// p.Age = 31; // ❌ 编译错误

👍 优势:

  • 与面向对象封装天然适配
  • 保留不可变性同时支持初始化灵活性

🚩 5. 使用建议总结

使用场景 推荐关键词 理由
编译期不会变化的值(如 Pi) const 编译时已确定,性能更优
运行期动态初始化的字段 readonly 构造函数中灵活赋值,构造后不可变
想使用初始化表达式设定属性值 init 可读性强,避免创建多个构造函数
想实现不可变对象(immutable) init + get 提供只读接口,同时允许构造期间初始化

✅ 总结

关键词 可变性 赋值时机 使用场景
const 永远不可变 定义时 编译期常量
readonly 构造后不可变 构造函数或定义时 运行期常量,依赖构造动态赋值
init 构造后不可变 对象初始化表达式期间 封装属性,构造时赋值灵活

选择合适的不可变策略,可以帮助你写出更安全、清晰、易维护的代码!


📬 你更常用哪种不可变成员定义方式?欢迎评论区分享你的使用经验!

如果你觉得这篇文章有帮助,别忘了点赞、收藏和关注我~ 🚀

相关推荐
唐宋元明清21881 小时前
.NET 磁盘管理-技术方案选型
windows·c#·存储
故事不长丨1 小时前
C#正则表达式完全攻略:从基础到实战的全场景应用指南
开发语言·正则表达式·c#·regex
哈库纳玛塔塔2 小时前
放弃 MyBatis,拥抱新一代 Java 数据访问库
java·开发语言·数据库·mybatis·orm·dbvisitor
phltxy2 小时前
从零入门JavaScript:基础语法全解析
开发语言·javascript
天“码”行空3 小时前
java面向对象的三大特性之一多态
java·开发语言·jvm
odoo中国4 小时前
Odoo 19 模块结构概述
开发语言·python·module·odoo·核心组件·py文件按
代码N年归来仍是新手村成员5 小时前
【Java转Go】即时通信系统代码分析(一)基础Server 构建
java·开发语言·golang
Z1Jxxx5 小时前
01序列01序列
开发语言·c++·算法
沐知全栈开发5 小时前
C语言中的强制类型转换
开发语言
关于不上作者榜就原神启动那件事6 小时前
Java中大量数据Excel导入导出的实现方案
java·开发语言·excel