Почему при обнаружении инициализатора типа возникает исключение NullReferenceException?

Это поставило меня в тупик. Я пытался оптимизировать некоторые тесты для Noda Time, где у нас есть проверка инициализатора типа. Я думал, что узнаю, имеет ли тип инициализатор типа (статический конструктор или статические переменные с инициализаторами )перед загрузкой всего в новый AppDomain. К моему удивлению, небольшой тест этого бросилNullReferenceException-несмотря на то, что в моем коде нет нулевых значений. Он только выдает исключение при компиляции без отладочной информации.

Вот короткая, но полная программа для демонстрации проблемы:

using System;

class Test
{
    static Test() {}

    static void Main()
    {
        var cctor = typeof(Test).TypeInitializer;
        Console.WriteLine("Got initializer? {0}", cctor != null);
    }    
}

И расшифровка составления и вывода:

c:\Users\Jon\Test>csc Test.cs
Microsoft (R) Visual C# Compiler version 4.0.30319.17626
for Microsoft (R).NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.


c:\Users\Jon\Test>test

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.
   at System.RuntimeType.GetConstructorImpl(BindingFlags bindingAttr, Binder bin
der, CallingConventions callConvention, Type[] types, ParameterModifier[] modifi
ers)
   at Test.Main()

c:\Users\Jon\Test>csc /debug+ Test.cs
Microsoft (R) Visual C# Compiler version 4.0.30319.17626
for Microsoft (R).NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.


c:\Users\Jon\Test>test
Got initializer? True

Теперь вы заметите, что я использую.NET 4.5 (релиз-кандидат)-который может быть уместным здесь. Мне было несколько сложно протестировать его с другими оригинальными фреймворками (, в частности с "ванильным".NET 4 ), но если у кого-то еще есть легкий доступ к машинам с другими фреймворками, мне были бы интересны результаты.

Прочие детали:

  • Я работаю на машине x64, но эта проблема возникает как со сборками x86, так и со сборками x64
  • Это «отладка -» кода , вызывающего , который имеет значение -, даже несмотря на то, что в приведенном выше тестовом примере он тестировал его на своей собственной сборке, когда я пробовал это против Noda Time, я не не нужно перекомпилировать NodaTime.dll, чтобы увидеть различия -, только Test.cs, которые ссылаются на него.
  • Запуск "сломанной" сборки на Mono 2.10.8 не приводит к броску

Любые идеи? Ошибка фреймворка?

РЕДАКТИРОВАТЬ :Все страньше и страньше. Если снять Console.WriteLineпозвонить:

using System;

class Test
{
    static Test() {}

    static void Main()
    {
        var cctor = typeof(Test).TypeInitializer;
    }    
}

Теперь только дает сбой при компиляции с csc /o- /debug-. Если вы включите оптимизацию,(/o+)оно работает. Но если вы включите вызов Console.WriteLineкак в оригинале, обе версии потерпят неудачу.

193
задан Jon Skeet 21 July 2012 в 06:17
поделиться