理解c#中的readonly,const与enum枚举

c#中的readonly,const与enum枚举大家都不会陌生

偶有空就来试试此三种类型的使用问题,其实CLR via中都有啦,高手可以略过

写一个测试类,如下。编译成一个单独的DLL

namespace lib

{

public class jm

{

public const string TSString = "a const string";

public readonly static string TSReadonly = "a readonly string";

public enum TSEnum

{

t1 = 0

}

}

}

再搞一个控制台程 序,很简就是为了调用上面的变量:

class Program
{
static void Main(string[] args)
{
Console.WriteLine("const:" lib.jm.TSString);

Console.WriteLine("readonly:" lib.jm.TSReadonly);

Console.WriteLine("Enum:" lib.jm.TSEnum.t1.GetHashCode().ToString());

Console.ReadLine();
}
}

引用上面的lib,如此的结果大家当然都知道.

好了。现在我们改变上面的lib中变量的值如下:

namespace lib
{
public class jm
{
public const string TSString = "a const string 2";

public readonly static string TSReadonly = "a readonly string 2";

public enum TSEnum
{
t1 = 2
}
}
}

我们在字符串后都加上2,枚兴的值也改为2

编译些DLL,但我们不重新编译调用的控制台程序,直接把DLL拷到控制台的debug下,替换原DLL,运行exe结果如下

除了readonly变化了以外。其余二个都没变。

为什么呢,我们可以用.net relector查看下il代码

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init ( [0] int32 CS$0$0000)
L_0000: nop
L_0001: ldstr "const:a const string"
L_0006: call void [mscorlib]System.Console::WriteLine(string)
L_000b: nop
L_000c: ldstr "readonly:"
L_0011: ldsfld string [lib]lib.jm::TSReadonly
L_0016: call string [mscorlib]System.String::Concat(string, string)
L_001b: call void [mscorlib]System.Console::WriteLine(string)
L_0020: nop
L_0021: ldstr "Enum:"
L_0026: ldc.i4.1
L_0027: box [lib]lib.jm/TSEnum
L_002c: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
L_0031: stloc.0
L_0032: ldloca.s CS$0$0000
L_0034: call instance string [mscorlib]System.Int32::ToString()
L_0039: call string [mscorlib]System.String::Concat(string, string)
L_003e: call void [mscorlib]System.Console::WriteLine(string)
L_0043: nop
L_0044: call string [mscorlib]System.Console::ReadLine()
L_0049: pop
L_004a: ret
}

我用红色标注的地方就可以看出原因了

const变量被编译后,调用的地方会直接内联值过去,枚举也类似,但readonly却不成,

所以这就是const的高效的地方了。

但当一个dll中的const 或enum改变把,其它使用它的程 序集也得重新编译。

其实const与readonly变量大家应该早就知道吧。我只是没想到eunm也是如此。学艺不精啊

 

补充:

当我把显示枚举的地方改为:Console.WriteLine("Enum:" lib.jm.TSEnum.t1.ToString());

输出为Enum:t1

这没有问题 

然后我把枚举改为:

public enum TSEnum
{
t2 = 1

}

也就是改变了枚举的t1为t2

然后拷贝DLL过来运行,得到的结果是Enum:t2.

所以它还是通过内联了值1再反过去找到值为1的t2。所以显示也是正确的

但当我把枚举改为:

public enum TSEnum
{
t2 = 2

}

也就是t1变为了t2,t1=1变为了t2=2

这时它就傻了。运行结果变成:Enum:1

只是把内联的值打印了出来。因为它找不到对应的枚举值了。

反编译可以看出“

L_0021: ldstr "Enum:"
L_0026: ldc.i4.1

L_0027: box [lib]lib.jm/TSEnum

把枚举的值装箱打印出来。所以是1

 

测试源码地址:http://www.jm47.com/document/2885

原文地址:https://www.cnblogs.com/jiamao/p/2125077.html