web-dev-qa-db-ja.com

静的コンストラクターの例外

私は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ブレーススタイルが気に入らない場合は申し訳ありませんが、ブレースを好みのAllmanスタイルに変更するためだけに投稿を編集しないでください。ありがとう。

36
James King

他の2つの回答は、直接的な質問に対する適切な回答です-メタ回答です-コンストラクターではなく、構成要素が設定されていないことが検出された場合、メソッドで例外をスローする必要があります。 IMHO、「未構成」は、SendMail時ではなく、コンストラクター段階でのこれらの要素の有効な構成状態です。それはこの問題全体を回避します。

24

型初期化子が一度失敗すると、再試行されることはありません。タイプは、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

ご覧のとおり、静的コンストラクターは一度だけ呼び出されます。

91
Jon Skeet
16