总结一下const和readonly

  1. const和readonly的值一旦初始化则都不再可以改写;
  2. const只能在声明时初始化;readonly既可以在声明时初始化也可以在构造器中初始化;
  3. const隐含static,不可以再写static const;readonly则不默认static,如需要可以写static readonly;
  4. const是编译期静态解析的常量(因此其表达式必须在编译时就可以求值);readonly则是运行期动态解析的常量;
  5. const既可用来修饰类中的成员,也可修饰函数体内的局部变量;readonly只可以用于修饰类中的成员

 

前面是我从网上摘录的,文字太多,懒得自己再总结和打字了.

 

注意,第四点尤为重要,我用以下代码来说明和验证:

 

 

 

1.建立文本文件,然后改成.cs文件-lib.cs:

 

 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConstReadonly_Base  
  7. {  
  8.     public class Test  
  9.     {  
  10.         public const double PI = 3.14;  
  11.         public static readonly double pi = 3.14;  
  12.     }  
  13. }  
 

 

 

 

 

 

2.在命令行中输入: csc /t:library lib.cs,就会生成一个lib.dll文件.

 

 

 

3.建立文本文件,然后改成.cs文件-demo.cs:

 

 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConstReadonly_Demo  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             Console.WriteLine(ConstReadonly_Base.Test.PI);  
  13.             Console.WriteLine(ConstReadonly_Base.Test.pi);  
  14.             Console.ReadKey();  
  15.         }  
  16.     }  
  17. }  

 

 

 

 

 

4.在命令行中输入: csc /r:lib.dll demo.cs,也就会生成一个demo.exe文件.

 

 

 

双击,结果如下:

 

3.14

 

3.14

 

 

 

5.更改lib.cs为:

 

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConstReadonly_Base  
  7. {  
  8.     public class Test  
  9.     {  
  10.         public const double PI = 3.1415;  
  11.         public static readonly double pi = 3.1415;  
  12.     }  
  13. }  
  

 

 

 

 

 

6.再次双击demo.exe文件,结果却如下:

 

3.14

 

3.1415

 

(注: 直接双击demo.exe是直接运行,不再编译,上结果也就是运行期结束的结果,相当于跳过了编译)

 

 

 

 

 

原因是什么呢?请听我慢慢道来.

 

 

 

用ILDasm工具(这里假定你会用),选择lib.dll,内容如下:

 

 

 

 

双击PI段:

 

内容为

 

  1. .field public static literal float64 PI = float64(3.1415000000000002)  

 

 

 

双击pi段:

 

内容为

 

  1. .field public static initonly float64 pi  

 

 

 

 

 

明显lib.cs被编译成元数据和IL汇编时,PI直接被替换成float64(3.1415000000000002)

 

而.cctor: void()静态构造函数中,

 

  1. .method private hidebysig specialname rtspecialname static   
  2.         void  .cctor() cil managed  
  3. {  
  4.   // Code size       15 (0xf)  
  5.   .maxstack  8  
  6.   IL_0000:  ldc.r8     3.1415000000000002  
  7.   IL_0009:  stsfld     float64 ConstReadonly_Base.Test::pi  
  8.   IL_000e:  ret  
  9. // end of method Test::.cctor  

pi是动态分配内存的,直到运行时才调用静态构造函数来初始化pi.

 

 

 

如果这时你还是不太明白,让我们接下去看:

 

用ILDasm工具,选择demo.exe,内容如下:

 

 

我们来看看Main函数中我们到底做了些什么:

 

  1. .method private hidebysig static void  Main(string[] args) cil managed  
  2. {  
  3.   .entrypoint  
  4.   // Code size       34 (0x22)  
  5.   .maxstack  8  
  6.   IL_0000:  nop  
  7.   IL_0001:  ldc.r8     3.1400000000000001  
  8.   IL_000a:  call       void [mscorlib]System.Console::WriteLine(float64)  
  9.   IL_000f:  nop  
  10.   IL_0010:  ldsfld     float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi  
  11.   IL_0015:  call       void [mscorlib]System.Console::WriteLine(float64)  
  12.   IL_001a:  nop  
  13.   IL_001b:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()  
  14.   IL_0020:  pop  
  15.   IL_0021:  ret  
  16. // end of method Program::Main  

WriteLine()打印PI时, 

 

 

 

  1. IL_0001:  ldc.r8     3.1400000000000001  
  2. IL_000a:  call       void [mscorlib]System.Console::WriteLine(float64)  

 

这说明编译时,PI被编译成一个常量.

WriteLine()打印pi时,

 

 

 

  1. IL_0010:  ldsfld     float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi  

这说明编译时,pi被编译成调用ConstReadonly_Base.Test::pi,可见pi量是动态分配和调用的.

 

posted @ 2013-06-30 21:30  小丑鱼1  阅读(236)  评论(0编辑  收藏  举报