该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const) | .Net中文网

编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const),本文由比特飞原创发布,转载务必在文章开头附带链接:编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const) | .Net中文网

该系列文章由比特飞原创发布,计划用半年时间写完全50篇文章,为大家提供编写高质量代码的一般准则。

1、概述

众所周知,.net 包含 2 种类型的常量,运行时常量和编译时常量,它们的表现行为不同,使用不当,会使你陷入困境。虽然编译时常量在执行上速度略快,但我依然强烈建议大家使用运行时常量(readonly),而不是编译时常量(const)。在继续深入了解之前,我们先要知道 .net 中两种常量各自的特点。

2、.net中两种常量的基本特点

我们看看以下代码片段:

两种常量的代码片段

我们很容易总结出它们各自的特点:

1、运行时常量 readonly 要么在定义的时候赋初始值,要么在构造函数中赋初始值;

2、编译时常量 const 必须在定义的时候赋初始值。

那我为什么建议大家使用运行时常量呢?因为编译时常量可能会使你已发行程序的表现的和你测试时不同,这是为什么呢?为了清楚的了解个中原委,我们要明白编译器为运行时常量和编译时常量都做了什么?

3、编译器为readonly和const关键字做了什么?

使用readonly修饰的常量为运行时常量,使用const修饰的常量为编译时常量,我们先来看两段示例代码:

public static readonly int ViewCount1 = 100;
public const int ViewCount2 = 100;

我们再来看一下两段代码的IL:

使用 DnSpy 解密的 IL 1

使用 DnSpy 解密的 IL 2

DnSpy 的反编译结果

从上面的反编译结果,可以明显的看出 const 为编译时常量,在编译期间已经被写到IL中。而 readonly 为运行时常量。Microsoft 技术支持文档中相关 IL 的解释也可以印证这一点。

Microsoft 技术支持文档中 ldsfld 的解释

Microsoft 技术支持文档中 Ldc_I4_S 的解释

当然,对于这个案例,输出的结果是一致的:

ViewCount1 和 ViewCount2 的输出结果

于是,我们得到以下重要结论:

1、const 和 readonly 在初始化一次后,不能再赋值;

2、const 在编译时被编译器所替换,而 readonly 在编译时只做校验,不作替换处理,运行时表现如同一般变量。

3、const 在 .net 中只能用于 数值型、字符型和 null,没有例外。

我们再看一个简单的示例:

public const int Birthday= 1986;
if(DateTime.UtcNow.Year == 1986)if(DateTime.UtcNow.Year == Birthday)

由我们之前的分析可以得知,它们是完全相同的。然而,并不是所有的情况下,你都能得到你所期望的结果,这又是为什么呢?

4、运行时所给出的结果,并不是你所期望的结果

某些情况下,运行时给出的结果与你所期望的结果大相径庭。现在我们有以下场景,你有一个已交付的软件,软件包含一个可执行主程序 EffectiveCoding02.exe ,一个被主程序所引用的类库 EffectiveCoding02.dll,主程序中包含以下代码:

public class SomeClass{public static readonly int StartValue = 100;public const int EndValue = 105;}

类库中包含以下代码:

for(var i = SomeClass.StartValue; i < SomeClass.EndValue; i++){console.WriteLine($"value = {i}");}

当初次交付程序给客户的时候,以上代码完全按照你的预期运行。后来由于软件迭代,你修改了主程序:

public class SomeClass{public static readonly int StartValue = 110;public const int EndValue = 115;}

重新编译后,因为你只更改了这个主程序,所以你将这个主程序交付给客户,然而你却得不到任何输出内容,程序没有按照你所预期的那样工作,于是你会说出那句开发人员的至理名言,“我这里是正常的啊!”。

产生这个问题的原因在于,由于编译时常量 const 是在编译时被编译器所替换的,所以虽然你进行了编译操作,然而用户计算机中的类库由于没有被编译器重新编译,所以用户计算机中的类库中的 EndValue 还是上一次编译时的结果,即105。然而运行时常量却以正常的方式运作,所以它的值变成了110,自然,你得不到任何的输出结果。因为循环初始值大于结束值。

5、总结

1、运行时常量 readonly 要么在定义的时候赋初始值,要么在构造函数中赋初始值;

2、编译时常量 const 必须在定义的时候赋初始值;

3、const 和 readonly 在初始化一次后,不能再赋值;

4、const 在编译时被编译器所替换,而 readonly 在编译时只做校验,不作替换处理,运行时表现如同一般变量;

5、const 在 .net 中只能用于 数值型、字符型和 null,没有例外;

6、尽量使用 readonly 常量,避免遇到已发行软件无法按预期运行的问题。

开发人员应牢记以上开发守则,否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你、唾弃你。

该系列文章由比特飞原创发布,计划用半年时间写完全50篇文章,为大家提供编写高质量代码的一般准则。

该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const) | .Net中文网

编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const)相关推荐

  1. 编写高质量代码的50条黄金守则-Day 04(首选字符串插值)

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 04(首选字符串插值) | .Net中文网. 编写高质量代码的50条黄金守则-Day 04(首选字符串插值),本文由比 ...

  2. 编写高质量代码的50条黄金守则-Day 03(首选is或as而不是强制类型转换)

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 03(首选is或as而不是强制类型转换) | .Net中文网. 编写高质量代码的50条黄金守则-Day 03(首选is ...

  3. 编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换)

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换) | .Net中文网. 编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换),本文 ...

  4. 编写高质量代码的50条黄金守则

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则 | .Net中文网. 概述 该系列文章由比特飞原创发布,计划用半年时间写完全50篇文章,为大家提供编写高质量代码的一般准则. ...

  5. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源...

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

  6. 读书笔记:编写高质量代码--web前端开发修炼之道(二:5章)

    读书笔记:编写高质量代码--web前端开发修炼之道 这本书看得断断续续,不连贯,笔记也是有些马虎了,想了解这本书内容的童鞋可以借鉴我的这篇笔记,希望对大家有帮助. 笔记有点长,所以分为一,二两个部分: ...

  7. 【备注】【C42】《编写高质量代码:改善Python程序的91个建议》PDF

    内容简介: 在通往"Python技术殿堂"的路上,本书将为你编写健壮.优雅.高质量的Python代码提供切实帮助!内容全部由Python编码的实践组成,从基本原则.惯用法.语法.库 ...

  8. 荐书与免费送书:《编写高质量代码改善 Python 程序的 91 个建议》

    为了学习如何打理好微信公众号,Python猫我关注了好几个python技术公众号.然后发现这些同行们都在免费送资源,或者抽奖送书耶.于是,我也去参与抽奖,竟然侥幸抽中啦一本<Python数据科学 ...

  9. 《编写高质量代码:改善c程序代码的125个建议》——建议2-6:防止无符号整数回绕...

    本节书摘来自华章计算机<编写高质量代码:改善c程序代码的125个建议>一书中的第1章,建议2-6,作者:马 伟 更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

最新文章

  1. 机器学习入门(12)— 激活函数层 ReLU、Sigmoid 层的实现
  2. 什么是CNN?机器学习入门贴,Facebook员工打造,47k访问量
  3. 作为一个测试人员,在你提出问题之前请先想想如下问题
  4. 卸载sharepoint2013
  5. python 实例方法调用时可以忽略第一个参数_盘点Python中易忽略的函数
  6. mysql dsn 连接_各种数据库的连接串(总结DSN的使用方法)
  7. 【数据结构与算法】之深入解析“求根节点到叶节点数字之和”的求解思路与算法示例
  8. 线性表:顺序栈算法实现
  9. 计算机专业英语mooc,专业英语(软件)-中国大学mooc-题库零氪
  10. android jenkins 动态版本,Jenkins工具(二)之 Jenkins集成android工程
  11. bzoj1783: [Usaco2010 Jan]Taking Turns
  12. mysql INSERT INTO table2 (column_name(s)) SELECT column_name(s) FROM table1;
  13. FFmpeg下载无损截取HLS视频流
  14. docker安装prestodb大数据查询引擎
  15. 删掉启动分区进不了系统,复活办法(win10)
  16. 简练网软考知识点整理-项目风险应对策略
  17. “蚂蚁牙黑,蚂蚁呀吼”一夜间火遍全网?别忽略了潜在风险
  18. java导入带图片的excel表格(工具HSSFWorkbook-HSSFSheet)(支持一条数据(单元格)可以导入多个图片,)
  19. Ammeter 仪表板控件
  20. 服务器主板显示不了独立显卡,独立显卡故障——如何才知道显卡和主板不兼容...

热门文章

  1. Linux Vim基本操作(文件的打开和编辑)完全攻略(有图有真相)
  2. Docker-基本概念(镜像和容器)
  3. 2022年有哪些值得学习的Java开源项目?这7个火爆了
  4. 静态类 c# 1614532739
  5. 演练 构造函数的显示调用与隐式调用 c# 1613715344
  6. 对象的使用 java 1613806439
  7. 数据结构与算法-什么是数据结构,什么是数据,什么是抽象数据类型
  8. python-random种子
  9. PHP设计模式之抽象工厂模式
  10. SoapUI测试webservice