Исключение в статическом конструкторе - PullRequest
32 голосов
/ 19 января 2011

Я нашёл SO, чтобы найти ответ на этот вопрос, и лучший, который я могу найти на данный момент, это здесь , однако он ориентирован на экземпляры со статическими конструкторами; Я использую класс только статически.

Мой код:

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 ()?

PS: Извините, если вам не нравится версия оформления скобок K & R, предложенная Страуструпом, но не редактируйте мой пост только для того, чтобы сменить скобки на предпочитаемый стиль Allman. Благодаря.

Ответы [ 3 ]

87 голосов
/ 19 января 2011

Как только инициализатор типа один раз завершился неудачей, он никогда не повторяется.Тип не работает на протяжении всего жизненного цикла 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

Как видите, статический конструктор вызывается только один раз.

24 голосов
/ 19 января 2011

Два других ответа являются хорошими ответами на ваш прямой вопрос - вот метаответ - вы должны вызывать исключение в методе, когда обнаруживаете, что элементы конфигурации не заполнены, а не в конструкторе. ИМХО, «не настроен» - это допустимое состояние конфигурации для этих элементов на этапе конструктора, но не во время SendMail. Это обойдет всю эту проблему.

...