2007年5月31日星期四

请使用static readonly,不要使用const

先放上两段代码。

代码1:

using System;

public class MyClass

{
public static void Main()

{

Console.WriteLine(Test.STR_1);

Console.WriteLine(Test.STR_2);

Console.ReadLine();

}
public class Test

{
public const string STR_1 = "Str1";

public static readonly string STR_2;

static Test()

{

STR_2 = "Str2";

}

}

}



代码2:

using System;

namespace

{

public class MyClass

{

// Constructors
public MyClass ()

{ }
// Methods

public static void Main ()

{

Console.WriteLine("Str1");

Console।WriteLine(MyClass.Test.STR_2);

Console.ReadLine();

}
// Nested Types

public class Test

{
// Constructors

static Test ()

{

MyClass.Test.STR_2 = "Str2";

}
public Test ()
{ }
// Constants

public const string STR_1 = "Str1";

// Statics

public static readonly string STR_2;

}

}

}

代码1和代码2最大的区别在于:代码2是使用反射技术从代码1编译生成的可执行文件"反编译"出来的。

贴这两段代码的目的就是为了说明一下static readonly 和const的区别。从代码2中可以看到,代码1里面的所有使用常量Test.STR_1的地方(只有一处,用红色标识),都被直接替换成了常量Test.STR_1所代表的字符串。而使用静态只读变量Test.STR_2的地方,代码1和代码2没有任何区别。

为什么会有这种情况?

因为常量在编译的时候值就已经被确定了,为了提高效率,编译器直接把程序中使用到的常量都替换为常量所代表的值了。

为什么我会想起来写这个?

因为我习惯把所用到的字符串和其他一些共用的值都表示为常量,放在一个独立的类库里,以便使用,结果,今天这个"以便"变成了不便。我修改了这个独立类库里面的某些字符串的值,编译类库之后,替换了服务器上的版本,现在大家都知道后果是什么了。由于服务器上引用这个类库的地方都是之前编译过的,唯独这个类库是新的,一个崭新的常量类库,可惜程序不会使用这些崭新的值,大家老老实实继续使用编译器提供的之前的常量代表的值。

为这事儿折腾了快两个小时,终于,想起了某个时候听说的关于常量的不方便之处,所以就出来提醒大家,以后尽量使用static readonly吧,更何况readonly还可以在构造函数中被赋值,呵呵。

没有评论: