• const与readonly的区别


    尽管你写了很多年的C#的代码,但是可能当别人问到你const与readonly的区别时候,还是会小小的愣一会吧~

          笔者也是在看欧立奇版的《.Net程序员面试宝典》的时候,才发现自己长久以来竟然在弄不清出两者的情况下,混用了这么长的时间。的确,const与readonly很像,都是将变量声明为只读,且在变量初始化后就不可改写。那么,const与readonly这两个修饰符到底区别在什么地方呢?其实,这个牵扯出C#语言中两种不同的常量类型:静态常量(compile-timeconstants)和动态常量(runtime constants)。这两者具有不同的特性,错误的使用不仅会损失效率,而且还会造成错误。

         首先先解释下什么是静态常量以及什么是动态常量。静态常量是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。而动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。

          当你大致了解上面的两个概念的时候,那么就可以来说明const与readonly了。const修饰的常量是上述中的第一种,即静态常量;而readonly则是第二种,即动态常量。那么区别可以通过静态常量与动态常量的特性来说明:

          1)const修饰的常量在声明的时候必须初始化;readonly修饰的常量则可以延迟到构造函数初始化 

          2)const修饰的常量在编译期间就被解析,即常量值被替换成初始化的值;readonly修饰的常量则延迟到运行的时候

          此外const常量既可以声明在类中也可以在函数体内,但是static readonly常量只能声明在类中。

          

          可能通过上述纯概念性的讲解,对有些初学者有些晕乎。下面就一些例子来说明下:      

    using System;
    class P
    {
        
    static readonly int A=B*10;
        
    static readonly int B=10;   
        
    public static void Main(string[] args)
        {
            Console.WriteLine(
    "A is {0},B is {1} ",A,B);
        }
    }

          对于上述代码,输出结果是多少?很多人会认为是A is 100,B is 10吧!其实,正确的输出结果是A is 0,B is 10。好吧,如果改成下面的话:

    using System;
    class P
    {
        
    const int A=B*10;
        
    const int B=10;   
        
    public static void Main(string[] args)
        {
            Console.WriteLine(
    "A is {0},B is {1} ",A,B);
        }
    }

           对于上述代码,输出结果又是多少呢?难道是A is 0,B is 10?其实又错了,这次正确的输出结果是A is 100,B is 10。

          那么为什么是这样的呢?其实在上面说了,const是静态常量,所以在编译的时候就将A与B的值确定下来了(即B变量时10,而A=B*10=10*10=100),那么Main函数中的输出当然是A is 100,B is 10啦。而staticreadonly则是动态常量,变量的值在编译期间不予以解析,所以开始都是默认值,像A与B都是int类型,故都是0。而在程序执行到A=B*10;所以A=0*10=0,程序接着执行到B=10这句时候,才会真正的B的初值10赋给B。如果,你还是不大清楚的话,我们可以借助于微软提供的ILDASM工具,只需在Vs 2008 Command下输入ILDASM就可以打开,如下所示:

            

            

            分别打开上述两个代码编译后产生的可执行文件,如下图所示:

                           

                       static readonly可执行程序的结构                                                                const可执行程序的结构

            在上述两张图中都可以看到A与B常量,分别双击节点可以看出其中的差异:

                  

                       static readonly修饰的常量A                                                                      const修饰的常量A

        

               

                      static readonly修饰的常量B                                                                       const修饰的常量B

             从上图中可以看出,const修饰的常量在编译期间便已将A,B的字面值算出来了,而static readonly修饰的常量则未解析,所以在Main函数中有以下的区别:

                        

                                  static readonly程序的Main函数                                                            const程序的Main函数

          从Main函数中我们可以看出,const的那个程序的输出直接是100与10,而readonly在输出的时候确实P::A与P::B,即将A与B常量的值延迟到运行的时候才去确定,故输出是0与10。

          那么对于静态常量以及动态常量还有什么特性呢?其实,静态常量只能被声明为简单的数据类型(int以及浮点型)、枚举、布尔或者字符串型,而动态常量则除了这些类型,还可以修饰一些对象类型。如DateTime类型,如下:

          //错误

          const DateTime time=new DateTime(); 

          //正确

          static readonly DateTime time=new DateTime();

         上述错误在于不能使用new关键字初始化一个静态常量,即便是一个值类型,因为new将会导致到运行时才能确定值,与静态变量编译时就确定字面值有悖。     

          欧书上最后给出了对静态常量与动态常量之间的比较,如下表所示:      

          

  • 相关阅读:
    codeforces 814B An express train to reveries
    codeforces 814A An abandoned sentiment from past
    codeforces 785D D. Anton and School
    codeforces 785C Anton and Fairy Tale
    codeforces 791C Bear and Different Names
    AOP详解
    Spring集成JUnit测试
    Spring整合web开发
    IOC装配Bean(注解方式)
    IOC装配Bean(XML方式)
  • 原文地址:https://www.cnblogs.com/zhangtao/p/1971868.html
Copyright © 2020-2023  润新知