【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 构造后不可变 对象初始化表达式期间 封装属性,构造时赋值灵活

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


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

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

相关推荐
方便面不加香菜2 分钟前
C++ 类和对象(二)
开发语言·c++
@大迁世界4 分钟前
20.“可复用组件”具体指的是什么?如何设计与产出这类组件?.
开发语言·前端·javascript·ecmascript
有味道的男人4 分钟前
电商效率翻倍:用 Open Claw 对接 1688 接口,快速实现图片选品 + 货源监控
java·开发语言·数据库
froginwe115 分钟前
Chart.js 雷达图:深入解析与实际应用
开发语言
枫叶丹45 分钟前
【HarmonyOS 6.0】屏幕管理新特性:多屏坐标转换详解
开发语言·华为·harmonyos
Dxy12393102167 分钟前
Python有哪些方法可以进行文本纠错
开发语言·python
fengci.18 分钟前
php反序列化(复习)(第四章)
android·开发语言·学习·php·android studio
Jasmine_llq18 分钟前
《B3923 [GESP202312 二级] 小杨做题》
开发语言·状态标记算法·顺序输入输出算法·递推迭代算法·循环遍历算法·条件终止算法·累加求和算法
游乐码20 分钟前
C#Dicitionary
算法·c#