《CLR via C#》读书笔记(4) -- const与readonly的区别

个人认为两者都可以认为是常量,但是却又是有区别的。

 

首先看看两者所支持的类型:

const 只支持基元类型(所谓基元类型是指编译器直接支持的类型,也就是像int,char,string等等在C#编译器中定义了关键字的类型)。

readonly 可以支持所有类型。

 

然后再看看两者所限定常量的本质:

const 限定的是变量的引用以及变量所代表的值。

readonly仅仅限定的是变量的引用。(如果是引用类型的话,变量所代表的值是能够改变的)

 

最后看看编译器对这两者进行的处理:

const

当编译器遇到一个对const对象的引用时,编译器会将const变量所代表的值直接嵌入生成的IL代码中,也就是说编译完后这段代码和所引用的const变量就没有任何关系了。

这样的话如果我们在代码中修改了const变量的值然后只编译const变量所在程序集的话是不行的,必须为所有引用该变量的代码重新生成IL。

 

readonly

对于readonly的处理,编译器和对待其它的变量一样。因此编译后,调用代码对readonly的变量仍然是存在依赖的。在运行时,调用代码才会去访问readonly

变量所代表的对象的值。

 

写个小程序,生成IL验证一下:

 

public  class Constants
{
         public  const  string ConstName =  " Jensen ";

         public  static  readonly  int guard =  2;
}



class Program
{
         static  void Main( string[] args)
        {
            Console.WriteLine(Constants.ConstName);
            Console.WriteLine(Constants.guard);
            Console.ReadKey();
        }
}


让我们来瞅瞅生成的IL代码:

 

.method private hidebysig static void  Main(string [] args) cil managed
{
  .entrypoint
  // Code size       30 (0x1e)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Jensen"  --由于此处是对const变量的引用,编译器直接将它的值写入了IL代码中。
  IL_0006:  call       void  [ mscorlib ]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ldsfld     int32  [ Entity ]Entity.Constants::guard --此处是对readonly变量的引用,编译依然是保存了对guard变量运行时的依赖。
  IL_0011:  call       void  [ mscorlib ]System.Console::WriteLine(int32)
  IL_0016:  nop
  IL_0017:  call       valuetype  [ mscorlib ]System.ConsoleKeyInfo  [ mscorlib ]System.Console::ReadKey()
  IL_001c:  pop
  IL_001d:  ret
} // end of method Program::Main

 

 

转载于:https://www.cnblogs.com/Code-life/archive/2012/11/30/2796332.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值