. Обнаруженное исключение .NET неожиданно является нулевым

См. Ниже объяснение того, что происходит.

У меня действительно странная проблема, когда обнаруженное исключение имеет значение null.

Код использует MEF и изо всех сил пытается сообщить об ошибках композиции . Используя отладчик, я вижу, что генерируется исключение ( InvalidOperationException ), но когда оно перехватывается последним блоком catch в коде ниже, переменная ex имеет значение null. Это верно как в отладчике, так и при обычном выполнении кода.

static T ResolveWithErrorHandling() where T : class
{
    try
    {
        IocContainer.Compose(Settings.Default.IocConfiguration);
        return IocContainer.Resolve();
    }
    catch (ReflectionTypeLoadException ex)
    {
        // ... special error reporting for ReflectionTypeLoadException
    }
    catch (Exception ex)
    {
        // ex is null - that should not be possible!
        // ... general error reporting for other exception types
    }
    return null;
}

Код, который я заменил комментариями, действительно является простым кодом для форматирования сообщения об ошибке. Ничего странного там не происходит.

Я попытался изменить код, чтобы узнать, какой эффект это может иметь:

  • Если я удалю первый блок перехвата ( ReflectionTypeLoadException ), исключение, перехваченное в последнем блоке перехвата, перестанет быть нулевым.
  • Если я поймаю другой тип исключения в первом блоке перехвата, исключение, перехваченное в последнем блоке перехвата, больше не будет нулевым.
  • Если я добавлю блок перехвата для InvalidOperationException в качестве первого блока перехвата, исключение, пойманное в этом блоке, не является нулевым.
  • Если я добавлю блок перехвата для InvalidOperationException между двумя блоками перехвата, исключение, пойманное в этом блоке, будет пустым.

В проекте используется код Контракты и код, сгенерированный компилятором, подвергаются постобработке для проверки контрактов. К сожалению, я не знаю t придумал способ избавиться от этого в целях тестирования без серьезных операций над проектом.

Мой текущий обходной путь - не перехватывать ReflectionTypeLoadException и вместо этого переходить по типу ex в общем обработчике исключений.

Чем может быть объяснение такого «невозможного» поведения? Что случилось с блоком перехвата ReflectionTypeLoadException ?


Как ни странно, исключение не равно нулю и не может иметь значение NULL согласно стандарту C # 15.9.5.

Однако использование контрактов кода в проекте может испортить отображение локальных переменных в отладчике , потому что код IL, сгенерированный компилятором, может быть переписан с помощью контрактов кода, поэтому окончательный IL немного не синхронизируется с отладочной информацией. В моем случае переменная ex отображается как пустая, даже если это не так. Прискорбный характер сообщения об ошибке, происходящего непосредственно перед завершением работы приложения, означал, что я полагал, что сообщение об ошибке не вызывается в результате того, что ex имеет значение null и ex.Message вызывает NullReferenceException внутри моего блока catch. С помощью отладчика я смог «проверить», что ex было нулевым, но на самом деле не было нулевым.

Мое замешательство усугублялось тем фактом, что блок catch для ReflectionTypeLoadException похоже, влияет на проблему отображения отладчика.

Спасибо всем, кто ответил.

37
задан Community 23 May 2017 в 12:00
поделиться