在很多时候,或者很多朋友都认为const和readonly其实是一样的,它们都表示了一个不可变的值,也就是我们所谓的常量吧.它们的区别在于
- const是编译时常量
- readonly是运行时常量
那么,什么是编译时常量?也就是在编译时就决定了的常量,这样的好处是效率高。因为它直接就用常量值编译在所有引用的代码里面。如下面所示
//Compile time constant:
public cocnst int _Millennium = 2000;
一个编译时常量会被目标代码中的值直接取代。下面的代码:
if(myDateTime.Year == _Millennium)
会与下面写的代码编译成完全相同的IL代码:
if(myDateTime.Year == 2000)
如果这样,当然效率会比较高。但是,这样做会有下面一个问题
假设有一个主程序,它会引用另外一个程序集,而该程序集中使用了const常量。我们来看看
1. 程序集(代码很简单)
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
public class Class1
{
public const string VERSION = "VERSION 1.0";
}
}
2. 主程序
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ClassLibrary1.Class1.VERSION);
Console.Read();
}
}
3.调试程序,当然是可以很正确地显示出来版本号
4. 假设我们此时,对ClassLibrary1进行了更新,修改了常量值
public class Class1
{
public const string VERSION = "VERSION 2.0";
}
5. 此时,我们重新编译ClassLibrary。
【注意】我们不编译主程序。直接把ClassLibrary的编译结果复制过去。
6. 此时运行主程序,你会发现主程序仍然是显示出来VERSION 1.0
你很诧异对吧?但这就是编译时常量的结果。我们可以来看看主程序里面的MSIL代码
你可以看到,其实在MSIL里面已经将VERSION 1.0进行了硬编码,也就是说,除非你重新编译主程序,它才会更改这个常量的值。
反过来说,如果在ClassLibrary中使用readonly变量,则在MSIL中保存的是一个变量的引用,那么这就叫运行时常量,它会动态读取程序集中的常量值。
public static readonly string Author = "Chenxizhang";//定义运行时常量
通过上面的讲解,我们可以得出一个结论
1. 如果一个常量永远不会变化,那么可以使用const定义常量,这样可以获得更加好的性能。(虽然性能其实相差不大)
2. 反之,则应该优先考虑用readonly