c# const 和 readonly 的区别

发布时间 - 2026-01-09 00:00:00    点击率:
const值编译时内联,更新需全量重编译;readonly运行时初始化,支持复杂类型和构造函数赋值,static readonly适用于跨程序集安全更新。

const 只能在编译时确定值,改了就得全量重编译

如果你把一个配置写成 const string ApiUrl = "https://api.example.com";,那这个字符串不是“存在内存里”,而是被 C# 编译器直接**替换进所有调用它的 IL 代码中**。这意味着:一旦你更新了这个常量、发布新版本的类库,但调用方没重新编译——它还在用旧地址。

  • 常见错误现象:ApiUrl 在类库中已改成 "https://new-api.example.com",但老客户端仍请求旧地址,且日志/调试都看不出问题
  • 适用场景:数学常量(const double Pi = 3.14159;)、固定协议标识(const string ContentTypeJson = "application/json";)这类真正“永不变”的值
  • 不能用于需要运行时计算的值,比如 DateTime.Now.ToString()Environment.GetFolderPath(...) —— 编译器直接报错

readonly 支持运行时赋值,能用在构造函数和复杂类型上

readonly 字段不是“编译期硬编码”,而是在对象创建过程中(声明时或构造函数里)一次性赋值,之后禁止修改。它不挑类型,也不要求“编译期可算”。

  • 支持任意类型:数组、自定义类、DateTimeGuid、甚至 HttpClient 实例(只要确保只初始化一次)
  • 可以是实例级或静态级:readonly string InstanceId 每个对象不同;static readonly Guid AppId 全局一份
  • 常见错误:在普通方法里试图赋值 this.Timeout = 30; → 编译错误 CS0198:“无法对只读字段赋值”
public class ServiceClient
{
    public readonly int Timeout;
    public readonly DateTime CreatedAt;
    public readonly HttpClient Http;
public ServiceClient(int timeout)
{
    Timeout = timeout;              // ✅ 构造函数中赋值 OK
    CreatedAt = DateTime.UtcNow;   // ✅ DateTime 支持
    Http = new HttpClient();       // ✅ 引用类型也 OK
}

}

const 隐含 static,readonly 默认是实例级

你写 const int MaxRetries = 3;,它天然就是类级别的,只能通过 MyClass.MaxRetries 访问,不能用实例去点 —— 即使写了 var x = new MyClass(); x.MaxRetries,编译器也会报错。

  • readonly 字段默认属于实例:每个对象都有自己的一份副本(比如缓存路径、用户 ID 等)
  • 要让它变成类级别?加 static readonly,例如:static readonly string ConfigPath = Path.Combine(AppContext.BaseDirectory, "config.json");
  • 不能写 static const —— 语法错误,因为 const 已经是静态的了

选哪个?看三件事:能不能编译期确定、类型是否受限、要不要跨程序集安全更新

这不是风格偏好,而是行为差异带来的实际后果。尤其当你在写 NuGet 包或基础类库时,选错会埋坑。

  • 值是 int/string/enum,且确认永远不变 → 用 const(性能略高,无内存开销)
  • 值依赖构造参数、环境变量、配置文件、或类型是 List/DateTime/object → 必须用 readonly
  • 要发布给外部项目用?优先选 static readonly 而非 const,否则别人升级你的包却没重编译,就会拿到过期值

容易被忽略的一点:即使你用 readonly,也不能阻止反射强行修改(FieldInfo.SetValue(...)),但它至少守住编译期和常规运行时的契约。而 const 的“不可变”是编译器强制内联的结果,连反射都改不了——因为根本没字段存在。


# js  # json  # 编码  # app  # 环境变量  # 配置文件  # 区别  # c#  # 编译错误  # Static  # String  # Object  # 常量  # 构造函数  # const  # enum  # 字符串  # int  # double  # var  # 对象  # this  # https  # 集安  # 类库  # 时计  # 报错  # 自己的  # 就会  # 也不  # 都有  # 也会  # 还在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】  bootstrap日历插件datetimepicker使用方法  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  iOS中将个别页面强制横屏其他页面竖屏  在centOS 7安装mysql 5.7的详细教程  高端建站如何打造兼具美学与转化的品牌官网?  HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】  Python文件流缓冲机制_IO性能解析【教程】  如何实现javascript表单验证_正则表达式有哪些实用技巧  制作公司内部网站有哪些,内网如何建网站?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  如何快速登录WAP自助建站平台?  如何用花生壳三步快速搭建专属网站?  QQ浏览器网页版登录入口 个人中心在线进入  高性能网站服务器配置指南:安全稳定与高效建站核心方案  如何在腾讯云服务器快速搭建个人网站?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  javascript中对象的定义、使用以及对象和原型链操作小结  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  如何用AI帮你把自己的生活经历写成一个有趣的故事?  java ZXing生成二维码及条码实例分享  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  香港服务器选型指南:免备案配置与高效建站方案解析  Laravel Seeder填充数据教程_Laravel模型工厂Factory使用  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  EditPlus中的正则表达式 实战(4)  如何在Windows服务器上快速搭建网站?  黑客如何利用漏洞与弱口令入侵网站服务器?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  桂林网站制作公司有哪些,桂林马拉松怎么报名?  Laravel如何操作JSON类型的数据库字段?(Eloquent示例)  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏  零基础网站服务器架设实战:轻量应用与域名解析配置指南  如何安全更换建站之星模板并保留数据?  如何用美橙互联一键搭建多站合一网站?  Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优  如何快速搭建高效WAP手机网站?  Win11关机界面怎么改_Win11自定义关机画面设置【工具】  Laravel怎么使用Intervention Image库处理图片上传和缩放  Android利用动画实现背景逐渐变暗