2011-01-19 13 views
28

Wykopałem SO, aby znaleźć odpowiedź na to pytanie, a najlepszym, jaki mogę znaleźć do tej pory, jest here, jednak jest ono ukierunkowane na instancje z konstruktorami statycznymi; Używam klasy tylko statycznie.Wyjątek w konstruktorze statycznym

Mój kod:

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); 


. 

Więc jeśli statyczny konstruktor zgłasza wyjątek po raz pierwszy nazywa, co dzieje się drugi raz spróbować uzyskać dostęp do metody statycznej sendmail()?

PS: Przepraszam, jeśli nie podoba ci się wersja stylu K Stroustrup K & R, ale nie edytuj mojego posta tylko po to, aby zmienić nawiasy klamrowe na preferowany styl Allmana. Dzięki.

+0

To powinno się nie udać, ale co jest nie tak z wypróbowaniem tego dla siebie? –

+0

Nie sądzę, że naprawdę ma sens rzut z konstruktora (statyczny), ponieważ wtedy klasa jest w stanie niestabilnym (nie w pełni zainicjowany). A co z tworzeniem jawnej funkcji 'Init()', którą wywołujesz przed użyciem (nie powinieneś nic robić, jeśli już została zainicjalizowana) i jeśli zgłasza wyjątek, * nie używaj klasy * – Cameron

+0

Pontus> Myślałem, że Jon może potrzebować czegoś więcej punktów:) –

Odpowiedz

22

Pozostałe dwie odpowiedzi są dobre odpowiedzi na bezpośrednie pytanie - oto metaanswer - powinieneś rzucać wyjątek w metodzie, gdy wykryje, że elementy konfiguracyjne nie są wypełnione, a nie w konstruktorze. IMHO, "nieskonfigurowane" jest prawidłowym stanem konfiguracji dla tych elementów w fazie konstruktora, ale nie w czasie wysyłania wiadomości. To obejmie cały ten problem.

+0

+1, interesująca perspektywa –

+1

Jon właściwie odpowiedział na moje pytanie najbardziej poprawnie, ale ta odpowiedź proponuje lepsze rozwiązanie niż ta, którą mam. –

81

Po jednorazowym niepowodzeniu inicjalizatora typu, nie jest on nigdy ponawiany. Typ jest martwy przez całe życie AppDomain. (Zauważ, że dotyczy to wszystkich inicjalizatorów typów, nie tylko typów z konstruktorami statycznymi: typ ze statycznymi zmiennymi z wyrażeniami inicjalizacyjnymi, ale bez konstruktorów statycznych, może wykazywać subtelne różnice w czasie wykonywania inicjatora typu - ale będzie to jeszcze tylko zdarzyć raz)

demonstracje.

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); 
      } 
     } 
    } 
} 

wyjściowa:

In static constructor 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 

Jak widać, statyczny konstruktor nazywa się tylko raz.

+4

Interesujące jest, że przechwytujesz tylko 'TypeInitializationExceptions' kiedy jawnie rzucasz' Exception' ... czy '' Exception' zostaje połknięty? –

+7

@ James B: Nie, jest to wyjątek InnerException wyjątku TypeInitializerException. –

+0

Ah! Mam nadzieję, że nie masz nic przeciwko, że przyznałem odpowiedź Chrisowi ... Twoje pytanie właściwie odpowiada na pytanie, które zadawałem i było najbardziej pomocne w zrozumieniu oczekiwanego zachowania, ale spodobało mi się jego rozwiązanie, aby uniknąć problemów z moim podejściem. Catching TypeInitializationExceptions wszędzie, gdzie wykonuję statyczne połączenia z moją klasą, nie brzmi jak zabawa! Dzięki za pomoc! –

Powiązane problemy