常量在代码里时有出现,然而它却存在版本问题。
示例:
在一个Main函数里调用另外一个dll,记为Lib.dll里的一个常量值。
Main函数代码:
using Lib;
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine(ConstValue.MaxIntSize);
}
}
Lib.dll里的代码:
using System;
namespace Lib
{
public class ConstValue
{
public const Int32 MaxIntSize = 32;
}
}
对Main函数与Lib.dll都进行编译后,假设编译后的exe为Study.exe。在命令行执行 Study.exe
输出:
32
此时,将MaxIntSize改为64,如下:
using System;
namespace Lib
{
public class ConstValue
{
public const Int32 MaxIntSize = 64;
}
}
并对Lib.dll进行重新编译,并将编译后的Lib.dll重新放回到Main所能引用到的目录,覆盖原来的旧版本;
再次执行Study.exe
输出:
32
说明并没有达到预期的变化。
原因
利用ildasm.exe打开Study.exe,可以看到:
在这里,C#编译器已经将MaxIntSize常量编译到Main函数的代码之中,执行时,并不访问Lib.dll,即使将Lib.dll删除也不会影响执行的结果 。
因此,在无法确定常量是否会发生变化时,最好不要使用常量 。而应该改用readonly变量。
示例:
Main函数代码:
using Lib;
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine(new ReadonlyValue().MaxIntSize);
}
}
Lib.dll中的代码:
using System;
namespace TestLibrary
{
public class ReadonlyValue
{
public readonly Int32 MaxIntSize = 32;
}
}
对Main与Lib都进行编译,利用ildasm.exe打开Study.exe可以看到:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 18 (0x12)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [TestLibrary]Lib.ReadonlyValue::.ctor()
IL_0006: ldfld int32 [TestLibrary]Lib.ReadonlyValue::MaxIntSize
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: ret
} // end of method Program::Main
{
.entrypoint
// Code size 18 (0x12)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [TestLibrary]Lib.ReadonlyValue::.ctor()
IL_0006: ldfld int32 [TestLibrary]Lib.ReadonlyValue::MaxIntSize
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: ret
} // end of method Program::Main
在这里,Main的每次执行都会调用 Lib.dll里的ReadonlyValue类,并创建一个实例对象。因此,重新编译之后的dll也能够得到Main函数的调用。只不过由于要创建新的对象,所以在性能上稍微差点,不过,如果不是大量创建,影响不大。