2011-01-19 21 views
28

私はこれを解決するためにSOを掘り出しました。これまで見つかった最良のものはhereですが、これは静的コンストラクタを使用するインスタンスに対応しています。私は静的にクラスを使用しています。静的コンストラクタの例外

マイコード:

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


. 

静的コンストラクタが例外にそれを呼び出して初めてスローのであれば、どのような私は、静的なのSendMail()メソッドにアクセスしようとする2回目に発生?

PS:StroustrupのバージョンK & Rブレーススタイリングが気に入らないのは残念ですが、あなたの好みのオールマンスタイルにブレースを変更するために投稿を編集しないでください。ありがとう。

+0

これは失敗するはずですが、自分で試してみると何が問題になりますか? –

+0

クラスが不安定な状態(完全に初期化されていない状態)にあるので、(静的な)コンストラクタからスローするのは本当に意味がないと思います。使用前に呼び出す明示的な 'Init()'関数を作成する方法(既に初期化されている場合は何もしないでください)、例外がスローされた場合*クラスを使用しないでください* – Cameron

+0

Pontus> Jonがより多くの点:) –

答えて

22

他の2つの答えはあなたの直接の質問に良い答えです - ここmetaanswerだ - あなたはメソッドで例外をスローする必要がありますが、構成要素ではないことを検出したときコンストラクタではなく、データが格納されます。 IMHOは、 "設定されていません"は、コンストラクタフェーズでのこれらの要素の有効な構成状態です。SendMail時ではありません。それはこの問題全体を回避するでしょう。

+0

+1、興味深い見通し –

+1

ジョンは実際に私の質問に最も正確に答えましたが、この回答は私が持っているものより良い解決策を提案しています。 –

81

タイプイニシャライザが一度失敗すると、再試行されません。 AppDomainの存続期間中は型が死んでいます。 (これは、静的コンストラクタを持つ型だけでなく、すべての型初期化子に当てはまります。初期化子式を持つ静的変数を持つ型ですが、静的コンストラクタを持たない型は、初期化子の実行タイミングに微妙な違いがあります。まだ一度だけ起こる)

デモンストレーション:。

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

出力:あなたが見ることができるように

In static constructor 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 
TypeInitializationException 

、静的コンストラクタは一度だけ呼ばれます。 MSDNから

+4

明示的に 'Exception'を投げたときに' TypeInitializationExceptions'だけを捕まえるのは面白いのですが... 'Exception'は飲み込まれますか? –

+7

@James B:いいえ、TypeInitializerExceptionのInnerExceptionにあります。 –

+0

ああ!私はChrisに答えを与えました...あなたの質問は、私が求めていた質問に実際に答えて、期待される行動を理解するのに最も役立ちましたが、私のアプローチの問題を避けるために彼のソリューションが好きでした。私のクラスへの静的な呼び出しをどこでも行うことができるように、TypeInitializationExceptionをキャッチするのは面白いとは言えません!ご協力いただきありがとうございます! –

関連する問題