正文

慎用const关键字2006-07-24 13:39:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/Csharpsky/16781.html

分享到:

 我们在coding的时候,经常会做一个Config类,里面定义一些系统的公用变量。
      可能里面会出现这样的代码: 

public const string PBD_Sys = @"……";
      也有可能会有人写成这样的样子:
public static readonly string TempUnZipFilePath = "NewVersion";
      那么,这两种方式究竟有哪些不同呢?一个是采用的const,一个采用static readonly。
      
      这个涉及到一点编译器的工作方式。比如说,上面的代码出现在类config中,config所在的project,我们命名为A。我们在projectB中调用projectA,这个时候,const和static readonly就会有一些小小的区别,有的时候,这个小小的区别,就会造成一个重大的bug
      代码如下(Project A中):
      
public class Config
    
{
        
public const string PBDSys = "PDB";

        
public static readonly string TempUnZipFilePath = "NewVersion";
    }

      Project B中(为了说明问题,本例中B是一个控制台应用程序):
      
    [STAThread]
        
static void Main(string[] args)
        
{                
            Console.WriteLine(Config.PBDSys);

            Console.WriteLine(Config.TempUnZipFilePath);
        }
    
      
      显而易见,结果如下:
      PDB
      NewVersion

      这个时候,如果修改Project A中的代码如下:
public class Config
    
{
        
public const string PBDSys = "PDBE";

        
public static readonly string TempUnZipFilePath = "OldVersion";
    }

      然后重新编译A。再次运行ProjectB的Bin目录下的EXE。结果将会比较有趣。
      PDB
      OldVersion

      这里就体现了const关键字和readonly关键字的差异。
      C#在处理const关键字的时候,直接嵌入值来进行编译。
      而在处理readonly关键字的时候,是动态引用的。查看IL,可以很明显的看到两者的区别。

 

.method private hidebysig static void Main(string[] args) cil managed
{
      .custom instance 
void [mscorlib]System.STAThreadAttribute::.ctor()
      .entrypoint
      
// Code Size: 21 byte(s)
      .maxstack 1
      L_0000: ldstr 
"PDB" //直接加载const
      L_0005: call void [mscorlib]System.Console::WriteLine(string)
      L_000a: ldsfld 
string ConsoleApplication1.Config::TempUnZipFilePath //引用加载readonly变量的值
      L_000f: call void [mscorlib]System.Console::WriteLine(string)
      L_0014: ret 
}


      所以,我们要注意到这个细节,确保一个值一定是一个常量的时候,才采用const关键字。否则,当我们发布程序的时候(尤其是插件式的这种),会有些不可预知的错误发生。本来客户仅仅需要Down一个新版本的dll就可以了,但是如果采用const关键字的话,可能会导致客户需要更新所有的装配件才能获取新版本的功能。

 

 

const是complier-time就推演出来了;readonly是run-time时推演的。
IL
一个const是硬编码的hard-code
EXP:
.field public static literal int32 Cvalue = int32(0x00000078)

IL_0000: ldc.i4.s 105
IL_0002: stsfld int32 constVSreadonly.interfaceData::SRvalue
IL_0007: ret

一个readonly在IL中的编码却不是
.field public static initonly int32 SRvalue

IL_0002: stsfld int32 constVSreadonly.interfaceData::SRvalue

阅读(3057) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册