zoukankan      html  css  js  c++  java
  • const 常量 和 readonly 常量 的区别[摘]

    详细解释下 const 常量 和 readonly 常量 的区别吧。
    前者是编译时常量,后者是运行时常量。
    一般的,Java阵营认为不需要区分两者,把编译时常量和运行时常量交给编译器去区分就可以了,所以在Java里面仅有一种常量 final。
    而 C# 则是让程序员自己能够定义。但是,在 Effective C# 的书中,作者强烈建议使用运行时常量 readonly 而不是编译时常量 const,为什么呢,我这里会解释。
    那么,什么是编译时常量呢?在编译的时候,编译器会把运行环境中所有的该变量替换成实际值。
    比如,
    const int i = 10;
    static void Main() {
         Console.WriteLine(i);
    }
    会被实际编译成
    static void Main() {
         Console.WriteLine(10);    // 注意,这里变量 i 被替换成了 10
    }
    若是编译器无法评估实际值,那么就无法使用 const 修饰符。
    所以,如下几类的代码是无效的:
    1、调用一个函数来获得值:
    const int i = GetValue();
    2、涉及到了构造函数:
    const SomeClass myObj = new SomeClass();
    如下几类的代码是合法的:
    const int i = 10 + 2 + 3;    // 合法,编译器能把 10 + 2 + 3 计算成 15
    const int j = i + 4;         // 合法,编译器能计算出 19
    const String s = "Hello" + "World";    // 依然合法
    编译时常量的好处:
    1、能够带来稍许的性能上的提升。
    实际运行的时候,程序不必计算表达式,因为表达式的值在编译的时候被编译器计算过了。
    2、能够给一些“神奇”的值命名。
    比如,这种代码是不好的:
    if (i > 30) {
        // 做某些事情
    }
    别人看到代码的时候,突然看到数字30,会很难明白这个30是做什么用的。这里30就是一个“神奇”的数值,除了作者,其他人很难弄懂它究竟是干嘛的。
    如果把上述代码改写成如下,会较好:
    const int maxFileCountToOpen = 30;
    if (i > maxFileCountToOpen) {
        // 做某些事情
    }
    代码编译出来的效果是一模一样的,但是在第二个例子中,我们给30命了一个名字,这样增强了程序的可读性。
    编译时常量的坏处:会带来版本问题
    比如,你要写一个DLL和一个EXE。在DLL中,定义了一个const常量。
    A.DLL
    --------------
    public class AFoo {
        public const int Foo = 10;
    }
    然后,在另外一个项目里面,叫做B.EXE,来引用AFoo.Foo
    B.EXE
    --------------
    public class BFoo {
        public static void Main() {
             Console.WriteLine(AFoo.Foo);
        }
    }
    运行B.EXE,会打印出 10。非常正确。
    若是我们现在要更新A.DLL的版本,把AFoo.Foo的值升级成20:
    A.DLL
    ----------------
    public class AFoo {
        // public const int Foo = 10;
        public const int Foo = 20;
    }
    编译好A.DLL。再次运行B.EXE,会是什么结果?结果还是会打印出10,而不是最新的版本里面包含的20。
    若是你能回答为什么,那么你就对 const 常量已经理解透了。
    一个技巧:若是一个常量的作用域是public,不要使用const修饰符。
    那么,什么是运行时常量呢?
    一般的,运行时常量 readonly 的值是在程序运行的时候被评估的,所以它不会带来性能上的提升。它唯一的好处就是,不允许该常量在运行时被修改。
    所以,如下的代码是合法的:
    readonly int a = GetValue();
    这里函数GetValue会在运行时被评估,然后结果被赋值给a,此后,a的值就不允许被修改。
    运行时常量 readonly 还有一个好处是,它可以在构造函数里面赋值:
    比如,如下的代码也是合法的:
    class SomeClass {
       readonly int b;
       public SomeClass() {
            b = GetValue();
       }
    }
    一个技巧:可以把一些常量定义成public,然后在构造函数里面赋值。
    最后一个特点。const常量都是默认static,所以const不可以和static混用。
    readonly 常量既可以是静态的,也可以是非静态的。所以,readonly 可以和 static 混用。

  • 相关阅读:
    [色彩校正] Gamma Correction
    需要齐次坐标的原因之二 所有的变换运算(平移、旋转、缩放)都可以用矩阵乘法来搞定
    需要齐次坐标的原因之一
    数据库连接类
    简单的数组排序
    OfficePage封装代码
    新闻管理数据模板
    最新page页码生成控件代码
    新闻管理cs页面
    快速收录新域名网站
  • 原文地址:https://www.cnblogs.com/flyinthesky/p/1574859.html
Copyright © 2011-2022 走看看