2011-01-19 16 views
28

Bu sorunun cevabı için SO'yu kazdım ve şu ana kadar bulabildiğim en iyisi here, ancak statik yapıcılarla örneklere yöneliktir; Sadece sınıfı statik olarak kullanıyorum.Statik kurucudaki istisna

Kodum:

public static class MailHelper { 

    private static string mailHost; 

    static MailHelper() { 

     var mailSettings = ConfigurationManager.GetSection("MailSettings") as NameValueCollection; 
     if (null == mailSettings) { 
      throw new ConfigurationErrorsException("Missing Mail Settings in the configuration file"); 
     } 

     mailHost = ConfigurationManager.AppSettings["mailHost"]; 
     if (null == mailHost) { 
      throw new ConfigurationErrorsException("Missing mailHost setting in the configuration file"); 
     } 

    } 

    public static void SendMail(MailMessage Message) { 
     ... 
    } 

} 


try { 
    MailHelper.SendMail(Message); 
} 
catch (ConfigurationErrorsException exc) { 
    ... 
} 

// ???  
MailHelper.SendMail(Message); 


. 

Yani statik yapıcı ben statik SendMail() yöntemini erişmeye çalıştığınızda ikinci kez ne bir istisna denir ilk kez atarsa?

Not: Stroustrup'ın K & R brace stilini beğenmediyseniz, ancak postlarımı yalnızca tercih ettiğiniz Allman stiline dönüştürmek için postumu düzenlemediyseniz üzgünüz. Teşekkürler.

+0

Başarısız olmalı, ama kendiniz için denemenin nesi yanlış? –

+0

(Statik) yapıcıdan atmak gerçekten bir anlam ifade etmiyor, çünkü sınıf kararsız bir durumda (tam olarak başlatılamıyor). Kullanmadan önce belirttiğiniz açık bir 'Init()' fonksiyonu yaratmaya (zaten başlatılmışsa hiçbir şey yapmamalı) ve bir istisna atarsa, * sınıfı kullanmayın * – Cameron

+0

Pontus daha fazla puan:) –

cevap

22

diğer iki cevabı da direkt soruya iyi cevaplar - burada metaanswer - sen yönteminde durum atma gerektiğini yapılandırma öğeleri olmadığını algıladığında Kurucu yerine, nüfuslu. IMHO, "yapılandırılmamış", SendMail zamanında değil, yapıcı aşamasında bu öğeler için geçerli bir yapılandırma durumudur. Bu bütün sorunu ortadan kaldıracaktır.

+0

+1, ilginç bir bakış açısı –

+1

Jon aslında benim sorumu en doğru şekilde yanıtladı, ancak bu cevap benim sahip olduğumdan daha iyi bir çözüm önerdi. –

81

Bir tür başlatıcı bir kez başarısız olduğunda, hiçbir zaman denenmez. Tip, AppDomain'in ömrü boyunca ölüdür. (Bu, yalnızca statik oluşturuculardaki türler için değil, tüm tür başlatıcıları için de geçerlidir. Başlatıcı ifadeleriyle statik değişkenlere sahip ancak statik kurucuları olmayan bir tür, başlatıcı yürütme tipinin zamanlamasında ince farklar gösterebilir - ancak hala sadece bir kez olur)

gösteri:.

using System; 

public sealed class Bang 
{ 
    static Bang() 
    { 
     Console.WriteLine("In static constructor"); 
     throw new Exception("Bang!"); 
    } 

    public static void Foo() {} 
} 

class Test 
{ 
    static void Main() 
    { 
     for (int i = 0; i < 5; i++) 
     { 
      try 
      { 
       Bang.Foo(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.GetType().Name); 
      } 
     } 
    } 
} 

Çıktı: Gördüğünüz gibi

In static constructor 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 

, statik yapıcı yalnızca bir kez denir. MSDN

+4

Açıkça "Özel Durum" a bastığınızda sadece 'TypeInitializationExceptions' ifadesini yakalamanız ilginç ... 'İstisna' yutuluyor mu? –

+7

@James B: Hayır, TypeInitializerException öğesinin InnerException dizinindedir. –

+0

Ah! Umarım sakıncası olmaz, cevabını Chris'e verdim ... Sorusu aslında sorduğum soruyu cevaplandırıyor ve beklenen davranışı anlamada en çok yardımcı oldu, ancak benim yaklaşımımla ilgili sorunları önlemek için çözümünü beğendim. Sınıfıma statik çağrı yaptığım her yerde TypeInitializationExceptions yakalamak eğlenceli gibi gelmiyor! Yardım ettiğin için teşekkür ederim! –