C#筆記 – 常量

常量
  • 常量值從不變化,因此總是被視為靜態成員
  • const int someConst = 1;
  • //Check in ildasm
    someConst : private static literal int32
  • 常量值必須能在編譯時確定,確定後,編譯器將常量保存到程序集元數據中

    • 因此,常量類型必須是編譯器可以識別的基元類型

    • C#允許定義非基元類型的常量,但值需設為null

  • 定義常量將導致元數據的創建

    • 代碼引用常量時,編譯器在定義常量的程序集的元數據中查找該常量並提取常量的值,然後將其嵌入生成的IL代碼中

    • 因此,由於常量值直接嵌入代碼中,所以運行時不需要為常量分配任何內存

    • 另外,不能獲取常量地址,也不能以傳引用的方式傳遞常量

  • 常量在版本控制上非常不方便

    • 假如有以下一個定義了常量的dll

      • public sealed class SomeLibraryType
        {
           public const int MaxEntriesInList = 1000;
        }
    • 有引用了上述dll,並引用了常量的exe

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

               Console.ReadLine();
          }
        }
    • 在生成exe時,編譯器會注意到引用的常量,並將常量直接嵌入到應用的IL代碼中;而不是去加載定義常量的DLL並取得常量值

      • 這使得即使重新修改並導出DLL文件也不會影響到應用程序裡嵌入的常量值

      • 應用程序必須重新打包一次、重新嵌入一次常量才可以更新常量值

      • IL_0000:  nop
        IL_0001: ldstr     "Max Entries supported in list: "
        IL_0006: ldc.i4     0x3e8
        IL_000b: stloc.0
        IL_000c: ldloca.s   V_0
        IL_000e: call       instance string [mscorlib]System.Int32::ToString()
        IL_0013: call       string [mscorlib]System.String::Concat(string,
        string)
        IL_0018: call       void [mscorlib]System.Console::WriteLine(string)

參考書目

  • 《CLR via C#》(第4版) Jeffrey Richter