程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [C#]跨模塊的可選參數與常量注意事項

[C#]跨模塊的可選參數與常量注意事項

編輯:C#入門知識

[C#]跨模塊的可選參數與常量注意事項


假設某個DLL裡有這麼一個類:  
1 // Lib.dll
2 public class Lib
3 {
4     public const string VERSION = "1.0";
5     public static void PrintVersion(string version = "1.0")
6     {
7         Console.WriteLine(version);
8     }
9 }

 

    然後有這麼個調用方:    
// Program.exe
class Program
{
    static void Main()
    {
        Console.WriteLine(Lib.VERSION);
        Lib.PrintVersion();
        Console.Read();
    }
}

 

  Program.exe的運行結果是顯而易見的:   1.0 1.0     過了一段時間,Lib更新版本了:    
// Lib.dll
public class Lib
{
    public const string VERSION = "2.0";
    public static void PrintVersion(string version = "2.0")
    {
        Console.WriteLine(version);
    }
}
 

 

  把Lib.dll重新編譯確保Program.exe引用了最新的DLL,然後再運行Program.exe,結果:   1.0 1.0 重新編譯Program.exe以後再次運行:   2.0 2.0 發現問題了吧,調用方必須重新編譯才能確保可選參數和常量的值是最新的。       原因是這樣的:    
 1 .method private hidebysig static 
 2     void Main () cil managed 
 3 {
 4     // Method begins at RVA 0x2050
 5     // Code size 30 (0x1e)
 6     .maxstack 8
 7     .entrypoint
 8 
 9     IL_0000: ldstr "1.0"
10     IL_0005: call void [mscorlib]System.Console::WriteLine(string)
11     IL_000a: ldstr "1.0"
12     IL_000f: call void CsConsole.Program/Lib::PrintVersion(string)
13     IL_0014: call int32 [mscorlib]System.Console::Read()
14     IL_0019: pop
15     IL_001a: ret
16 }

 

  這是第一次編譯之後Program.Main方法的IL,Lib.VERSION完全被編譯成了字面量"1.0"(第10行),而第11行的"1.0"是來自(第一次編譯時的)Lib.dll的元數據。 顯然,不管怎麼更新Lib的代碼,只要不重新編譯Program,這裡的兩個值就沒辦法得到更新,而實際的生產環境中經常沒法保證調用方會被重新編譯。 至於為什麼要這樣編譯,我是這麼理解的。 常量的值是在常量池裡待著的,通過類的成員去取值顯然是不如直接從常量池取來得方便快捷。 而可選參數的實現方式,則是在編譯時提前進行判斷與賦值,節省了運行時的時間。   解決方法: 對於可選參數,《CLR via C#》建議的方法是這樣的:
 
1 public static void PrintVersion(string version = null)
2 {
3     if (version == null)
4     {
5         version = "1.0";
6     }
7     Console.WriteLine(version);
8 }

 

  很顯然這段代碼的行為與之前相比是有變化的,但是大多數情況下確實可以解決值更新的問題,但是也帶來了運行時效率的問題。   對於常量,從我使用的示例就可以看出來,版本號這類的值不應該定義為常量,使用readonly可以達到目的。 而對於真正的常量,則不應該輕易地變更它的值。       最後嘛,Java雖然沒有const,但是static final也有同樣的表現,同樣需要注意這一點。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved