巧解C#單例模式引起的自定義異常

iDotNetSpace發表於2010-12-28

案例程式碼

對於單例模式,C#有個簡潔的實現,採用靜態的只讀欄位實現。

但是如果在單例模式建構函式中,發生了異常自定義異常,在客戶端能捕捉到嗎?

程式碼下載: ConfigException為我們定義異常類,TriggerException為異常觸發類。先不要執行,猜下會捕捉到什麼異常?

現實

事實上我們的自定義異常沒有沒Catch到,這是現象很隱蔽,主要是他不影響影響我們程式正常執行,只是我們費力定義的自定義異常都沒有起到任何的作用。
通常我們在單例模式的Portal工作,如果發生了異常,而如下日誌記錄的異常粒度對於運維一般參考價值不大

{"“ConsoleApplication4.Singleton”的型別初始值設定項引發異常。"} [System.TypeInitializationException]: {"“ConsoleApplication4.Singleton”的型別初始值設定項引發異常。"} Data: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: {"ComplicatedCalculate 的異常"} Message: "“ConsoleApplication4.Singleton”的型別初始值設定項引發異常。" Source: "ConsoleApplication4" StackTrace: " 在 ConsoleApplication4.Program.Main(String[] args) 位置 E:\\MyStudy\\ArchitectureHOL\\ConsoleApplication4\\ConsoleApplication4\\Program.cs:行號 16" TargetSite: {Void Main(System.String[])} 解決辦法

還是回到經典的單例模式的實現。程式碼如下: 

  1.  public class Singleton  
  2.     {  
  3.        public readonly static Singleton instance = null;  
  4.        private static object objectLock = new object();  
  5.        public int Age  
  6.        {  
  7.            get;set;  
  8.        }  
  9.        public static Singleton Instance  
  10.        {  
  11.            get 
  12.            {  
  13.                if (instance == null)  
  14.                {  
  15.                    lock (objectLock)  
  16.                    {  
  17.                        if (instance == null)  
  18.                            instance = new Singleton();  
  19.                    }  
  20.                }  
  21.                return instance;  
  22.            }  
  23.        }  
  24.  
  25.        private Singleton()  
  26.        {  
  27.            TriggerException t = new TriggerException();  
  28.            t.ComplicatedCalculate();  
  29.        }  

這樣就可以Catch到我們自定義的異常了。

原因和疑惑

為什麼字採用readonly Static 方式實現單例不能捕捉到自定的異常?這個也是呼叫建構函式Singleton進而觸發異常的,這個我解釋不清楚,也是我寫此文的主要目的,希望有人討論指點下。但是我想以下兩點很重要 :

C#靜態只讀欄位在作為動態常量在執行時賦值的時候出現異常,.Net FrameWork把他作為一個一般異常進行處理,把我們的自定義異常作為他的InnerException

C#靜態屬性在MSIL語言就是已經看作為一個方法了。所以其呼叫的方法異常會被Catch而返回上一級呼叫者。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-682719/,如需轉載,請註明出處,否則將追究法律責任。

相關文章