在写常量的时候,是选择使用 const 还是 static readonly 是一个让人难以决定的问题,本文告诉大家这两个方法的区别

如果一个类有静态字段,会如何初始化

可以使用的方法有两个,第一个方法就是直接在属性定义时写创建,第二个方法就是在构造创建,请看下面代码

    private static Test _test = new Test();

    private static Test _test;
static Demo()
{
_test = new Test();
}

再来思考下面的问题

请看下面两个代码有什么区别

    const string str = "xxxxx";
    static readonly string str = "xxxxx";
  • const 编译时常量

  • static readonly 运行时常量

修改两常量的值,生成新的Test.dll,然后运行Demo.exe(不编译)。

在不重新编译运行的时候,从上面的输出可以看到,使用const的值是不会修改,具体原因是因为 const 会被内联到代码

如写了下面的代码

        public void DeawelTurkisHotarwoWefudaybem()
{
var str = "德熙" + Foo;
} private const string Foo = "逗";

这时使用 Resharper 的 ILViewer ,在 Resharper 的 Resharper->Windows->ILViewer 打开,重新编译一下项目,把光标放在var str = "德熙" + Foo就可以看到类似下面代码的 IL 显示的是拼接了"德熙" + Foo的字符串

  .method public hidebysig instance void
DeawelTurkisHotarwoWefudaybem() cil managed
{
.maxstack 1
.locals init (
[0] string str
) // [8 9 - 8 10]
IL_0000: nop // [9 13 - 9 34]
IL_0001: ldstr "德熙逗"
IL_0006: stloc.0 // str // [10 9 - 10 10]
IL_0007: ret }

如果是方法内的常量也是会被内联代码,请看下面代码

        public void DeawelTurkisHotarwoWefudaybem()
{
const int n = 100;
var foo = n;
}

这时从 IL 可以创建的是下面的代码,定义的 n 是不存在的

  .method public hidebysig instance void
DeawelTurkisHotarwoWefudaybem() cil managed
{
.maxstack 1
.locals init (
[0] int32 foo
) // [9 9 - 9 10]
IL_0000: nop // [11 13 - 11 25]
IL_0001: ldc.i4.s 100 // 0x64
IL_0003: stloc.0 // foo // [12 9 - 12 10]
IL_0004: ret }

上面代码的IL_0001就是把一个int压入栈,压入的值是 100 ,也就是原来的定义的 n 就被去掉了,直接使用n的值

如果dll被其他100个工程引用的话,

每次修改 Test 的 const 变量后一定要重新 build 这100个工程,

不然的话这些工程里的const值就不会更新。

1.编译时常量更改时,引用该常量的程序集必须重新编译,

才能获取已更新的值。

2.运行时常量更改时,引用该常量的程序集不必重新编译,直接运行便可获得已更新的值。

对于隐式转换,如果是 const 支持隐式转换,如果是static readonly,不支持

(1)const常量在编译时解析;而static readonly常量在运行时解析。

(2)const常量必须在定义时初始化;而static readonly常量可以在定义时初始化,也可以在构造函数中初始化;

(3)非常确定不会改变的常量值可以用const,必须写在函数体内的常量需要用const,需要被attributes用到的常量应该用const。

(4)常量需要被客户端引用,且可能会改变,应该用static readonly。


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

C# const 和 readonly 有什么区别的更多相关文章

  1. const和readonly区别

    内容来源<<你必须知道的.NET>>(转载) 标题:什么才是不变:const和readonly 内容: const:用 const 修饰符声明的成员叫常量,是在编译期初始化并嵌 ...

  2. const和readonly的区别

    http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html http://www.codeproject.com/Tips/803 ...

  3. Const和readonly这间的区别和相同处

    相同:  const和readonly都是用来修饰常量的 不同: const 在申明之前就要对它初始化,readonly修饰的常量则可以到构造函数中初始化 const注重的是效率但是readonly注 ...

  4. const与readonly的区别

    const与readonly 很像,都是将变量声明为只读,且在变量初始化后就不可改写.那么,const与readonly 这两个修饰符到底区别在什么地方呢?其实,这个牵扯出C#语言中两种不同的常量类型 ...

  5. C# 总结const、 readonly、 static三者区别:

    总结const. readonly. static三者区别: (有人问我,看似简单,我也没能立刻回答出来,总结一下,分享一下.) const:静态常量,也称编译时常量(compile-time con ...

  6. 总结const、readonly、static三者的区别

    const:静态常量,也称编译时常量(compile-time constants),属于类型级,通过类名直接访问,被所有对象共享! a.叫编译时常量的原因是它编译时会将其替换为所对应的值: b.静态 ...

  7. C#中 const 和 readonly 的区别

    C#中 const 和 readonly 的区别 来源 https://www.cnblogs.com/gsk99/archive/2008/10/10/1308299.html http://dev ...

  8. C# 关键字const与readonly的区别

    尽管你写了很多年的C#的代码,但是可能当别人问到你const与readonly的区别时候,还是会小小的愣一会吧~ 笔者也是在看欧立奇版的<.Net 程序员面试宝典>的时候,才发现自己长久以 ...

  9. 转:总结const、readonly、static三者的区别

    const:静态常量,也称编译时常量(compile-time constants),属于类型级,通过类名直接访问,被所有对象共享! a.叫编译时常量的原因是它编译时会将其替换为所对应的值: b.静态 ...

随机推荐

  1. BootstrapValidation一些tips

    BootstrapValidation一些tips:1. callback的用法 如果你有一些特别的检查需要,比如两个元素必需有一个有值,你可以在两个元素上加上callback,例:sel和cb必需有 ...

  2. PAT天梯赛L1-002 打印漏斗

    题目链接:点击打开链接 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个"*",要求按下列格式打印 ***** *** * *** ***** 所谓"沙漏形 ...

  3. 从零学React Native之12 组件的生命周期

    一个React Native组件从它被加载,到最终被卸载会经历一个完整的生命周期.所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命周期,是合理开发的关键. ES6语法和之前的ES5 ...

  4. POJ 2632 Crashing Robots (模拟 坐标调整)(fflush导致RE)

    题目链接:http://poj.org/problem?id=2632 先话说昨天顺利1Y之后,直到今天下午才再出题 TAT,真是刷题计划深似海,从此AC是路人- - 本来2632是道略微恶心点的模拟 ...

  5. AT2346 No Need

    atcoder上的题目 链接 一道思维题目 可以发现如果X是可有可无的,那么所有小于X的数也一定是可有可无的, 所有我们只要找出最大的那个可有可无的数字就好了 进一步分析,发现 若A1, A2, . ...

  6. Libevent:4event loop

    一:运行loop       一旦一些events在event_base注册之后(下一节会讨论如何创建和注册events),就可以使Libevent等待events,并且在events准备好时能够通知 ...

  7. docker images列出镜像

    命令:docker images Usage: docker images [OPTIONS] [REPOSITORY[:TAG]] List images Options: -a, --all Sh ...

  8. WPF 线段Line过长渲染出现的问题

    原文:WPF 线段Line过长渲染出现的问题 在使用WPF的时候,可以做一个实验,在canvas里添加一条线段Line,StrokeThickness属性设置为1,然后通过放大canvas或者调整li ...

  9. @codeforces - 1209G2@ Into Blocks (hard version)

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 定义一个序列是好的,当且仅当这个序列中,相等的两个数之间的所有数 ...

  10. linux之docker

    简介 Docker是一个开源的应用容器引擎,基于go语言,遵循从Apache2.0协议开源 Docker可以让开发者打包他们的应用以及依赖包到一个轻量级,可移植的容器中,然后发布到任何流行的linux ...