43

これに対する答えを求めて 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);


.

では、静的コンストラクターが最初に呼び出されたときに例外をスローした場合、2 回目に静的な SendMail() メソッドにアクセスしようとするとどうなるでしょうか?

PS: Stroustrup のバージョンの K&R ブレース スタイルが気に入らない場合は申し訳ありませんが、ブレースを好みの Allman スタイルに変更するためだけに私の投稿を編集しないでください。ありがとう。

4

3 に答える 3

99

型初期化子が一度失敗すると、再試行されることはありません。この型は、AppDomain の存続期間中は無効です。(これは、静的コンストラクターを持つ型だけでなく、すべての型初期化子に当てはまることに注意してください。初期化子式を持つ静的変数を持ち、静的コンストラクターを持たない型は、型初期化子の実行のタイミングに微妙な違いを示す可能性がありますが、まだ1回しか発生しません。)

デモンストレーション:

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

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

于 2011-01-19T16:31:49.530 に答える
26

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

于 2011-01-19T16:34:43.540 に答える
19

Microsoft ドキュメント(静的コンストラクター (C# プログラミング ガイド))から:

静的コンストラクターが例外をスローした場合、ランタイムはそれを 2 回目に呼び出すことはなく、プログラムが実行されているアプリケーション ドメインの有効期間中、型は初期化されないままになります。ほとんどの場合、TypeInitializationException例外は、静的コンストラクターが型をインスタンス化できない場合、または静的コンストラクター内で未処理の例外が発生した場合にスローされます。ソース コードで明示的に定義されていない暗黙的な静的コンストラクターの場合、トラブルシューティングでは中間言語 (IL) コードの検査が必要になる場合があります。

于 2011-01-19T16:32:39.957 に答える