CLR via C# 定义常量将导致创建元数据

CLR via C# 定义常量将导致创建元数据

由于常量值从不变化,所以常量总是被视为类型定义的一部分。换言之,常量总是被视为静态成员,而不是实例成员。定义常量将导致创建元数据。

代码引用常量符号时,编译器在定义常量的程序集的元数据中查找该符号,提取常量的值,将值签入生成的 IL 代码中。由于常量的值直接嵌入代码,所以在运行时不需要为常量分配任何内存。除此之外,不能获取常量的地址,也不能以传引用的方式传递常量。这些限制意味着常量不能很好地支持跨程序集的版本控制。因此,只有确定一个符号的值从不变化才应定义常量。(将 MaxInt6定义为32767就是一个很好的例子)。下面来演示我刚才所说的内容。首先,请输入以下代码,并将其编译成一个 DLL 程序集。

using System;

pulbic sealed class SomeLibraryType {
    // 注意:C# 不允许为常量指定 static 关键字,
    // 因为常量总是隐式为 static
    public const Int32 MaxEntriesInList = 50;
}

接着用以下代码生成一个应用程序程序集:

用 csc.exe 的 /r 开关来引用刚才的.dll 文件。

using System;

public sealed class Program {
    public static void Main() {
        Console.WriteLine("Max entries supported in list: " + SomeLibraryType.MaxEntriesInList);
    }
}

注意代码引用了在 SomeLibraryType 类中定义的 MaxEntriesInList 常量。编译器生成引用程序代码时,会注意到 MaxEntriesInList 是值为 50 的常量符号,所以会将 Int3250 嵌入应用程序的 IL 代码,如下所示。事实上
,在生成了应用程序程序集之后,运行时根本不会加载 DLL 程序集,可以把它从磁盘上删除。

.method public hidebysig static void Main() cil managed 
{
    entrypoint 
    // Code size            25 (0x19)

    .maxstack 8 
    IL_0000: nop 
    IL_0001: ldstr          "Max entries supported in list: "
    IL_0006: ldc.i4.s       50
    IL_0008: box            [mscorlib]System.Int32
    IL_000d: call           string [mscorlib]System.String::Concat(object, object)
    IL_0012: call           void [mscorlib]System.Console::WriteLine(string)
    IL_0017: nop 
    IL_0018: ret
} // end of method Program::Main

这个例子清楚地展示了版本控制问题。如果开发人员将常量 MaxEntriesInList 的值更改为 1000,并且只是重新生成 DLL 1000,并且只是重新生成 DLL 程序集,那么应用程序集不受任何影响。应用程序要获得新值,也必须重新编译。如果希望在运行时从一个程序集中提取另一个程序集中的值,那么不应该使用常量,而应该使用 readonly 字段。

posted @ 2021-12-30 14:46  Destiny130  阅读(30)  评论(0)    收藏  举报