Исключения, сгенерированные в статических конструкторах

Если исключение сгенерировано, а в стеке нет обработчика, поэтому его поиск завершается в статическом конструкторе типа, то исполняющая система обрабатывает этот случай специальным образом. Она транслирует исключение в System. TypelnitializationException и генерирует его взамен первоначального.

Перед генерацией нового исключения свойство InnerException экземпляра TypelnitializationException устанавливается в исходное исключение. Таким образом, любой обработчик исключения инициализации типа может легко обнаружить причину сбоя.

Такая трансляция исключения имеет смысл, потому что конструкторы по своей природе не могут возвращать значение, свидетельствующее об успехе или неудаче. Исключения — единственный доступный механизм, который позволяет сигнализировать о сбое конструктора.

Что более важно: поскольку система вызывает статические конструкторы в определенное самой системой время, для них имеет смысл применять тип TypelnitializationException, который позволит точнее определить, когда что-то идет не так. Например, предположим, что имеется статический конструктор, который может потенциально генерировать исключение ArgumentOutOfRangeException.

Теперь представьте разочарование пользователей, если исключение распространится во включающем потоке в некоторый случайный момент времени, поскольку точный момент вызова статического конструктора определяется системой. Может показаться, что ArgumentOutOfRangeException материализуется буквально из ничего. Помещение исключения в оболочку TypelnitializationException немного проясняет ситуацию и предупреждает пользователей, или, надо надеяться, разработчика, о том, что проблема возникла во время инициализации типа.

В приведенном ниже коде демонстрируется пример того, как выглядит TypelnitializationException с вложенным внутри него исключением:

1
2
3
4
5
6
7
8
9
10
11
using System;
using System.10;
class EventLogger {
static EventLogger()  {
eventLog = File.CreateText ( "logfile.txt" );
// Следующий оператор сгенерирует исключение.
strLogName = (string) strLogName.Clone ();
}
static public void WriteLog ( string someText )  {
eventLog.Write ( someText );
}

Система может вызывать статические конструкторы во время загрузки типа или просто перед обращением к статическому члену, в зависимости от того, как сконфигурирована CLR для текущего процесса.

1
2
3
4
5
6
7
static private StreamWriter eventLog;
static private string strLogName;
}
public class EntryPoint {
static void Main()  {
EventLogger.WriteLog ( "Зарегистрировать это!" );
}

В результате запуска этого кода будет получен следующий вывод:

Unhandled Exception: System.TypelnitializationException:
The type initializer for ‘EventLogger1 threw
an exception. —> System.NullReferenceException:
Object reference not set to an instance of an object,
at EventLogger..cctor()
— End of inner exception stack trace — at EntryPoint.Main()

Необработанное исключение:
System.TypelnitializationException: Инициализатор типа EventLogger сгенерировал
исключение. —> System.NullReferenceException:
Объектная ссылка не установлена в экземпляр объекта. в EventLogger..cctor()
— Конец трассировки стека внутреннего исключения — в EntryPoint.Main()

Обратите внимание, что наряду с указанием того, что внешнее исключение имеет тип TypelnitializationException, вывод также показывает внутреннее исключение, с которого все началось — NullRef erenceException.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100