const和readonly

在很多时候,或者很多朋友都认为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.调试程序,当然是可以很正确地显示出来版本号

image

4. 假设我们此时,对ClassLibrary1进行了更新,修改了常量值

public class Class1
{
     public const string VERSION = "VERSION 2.0";
}

5. 此时,我们重新编译ClassLibrary。

【注意】我们不编译主程序。直接把ClassLibrary的编译结果复制过去。

6. 此时运行主程序,你会发现主程序仍然是显示出来VERSION 1.0

image

你很诧异对吧?但这就是编译时常量的结果。我们可以来看看主程序里面的MSIL代码

image

你可以看到,其实在MSIL里面已经将VERSION 1.0进行了硬编码,也就是说,除非你重新编译主程序,它才会更改这个常量的值。

反过来说,如果在ClassLibrary中使用readonly变量,则在MSIL中保存的是一个变量的引用,那么这就叫运行时常量,它会动态读取程序集中的常量值。

public static readonly string Author = "Chenxizhang";//定义运行时常量

image

通过上面的讲解,我们可以得出一个结论

1. 如果一个常量永远不会变化,那么可以使用const定义常量,这样可以获得更加好的性能。(虽然性能其实相差不大)

2. 反之,则应该优先考虑用readonly

原文地址:https://www.cnblogs.com/chenxizhang/p/1439400.html