Исключение в статическом конструкторе
Я выкопал 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: Извините, если вам не нравится Stroustrup версия стиля K & R brace, но не редактируйте мой пост, чтобы просто изменить фигурные скобки в ваш предпочтительный стиль Allman. Спасибо.
Ответы
Ответ 1
Два других ответа - это хорошие ответы на ваш прямой вопрос - здесь метаанализ - вы должны бросать исключение в метод, когда обнаруживаете, что элементы конфигурации не заполнены, а не в конструкторе. IMHO, "не настроено", является допустимым состоянием конфигурации для этих элементов на фазе конструктора, просто не во время отправки. Это обойдется всей этой проблемой.
Ответ 2
Как только инициализатор типа завершился с ошибкой один раз, он никогда не будет повторен. Тип мертв для жизни 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
Как вы можете видеть, статический конструктор вызывается только один раз.
Ответ 3
Из MSDN:
Если статический конструктор генерирует исключение, среда выполнения не будет вызывать его второй раз, и тип останется неинициализированным для времени жизни домена приложения в который работает в вашей программе.