Ошибка компилятора при использовании?. приводя к плохому изображению, которое не сработает PEVerify
Я наткнулся на что-то странное: я получил BadImageFormatException
, не зная, какое изображение (сборка) он мог бы назвать.
Я уменьшил решение, чтобы он состоял только из одного проекта без зависимостей:
![введите описание изображения здесь]()
Как вы можете видеть, он использует только System
(и mscorlib
), и, конечно же, я не загружаю сборки во время выполнения.
Он компилируется как AnyCpu с .NET 4.5.2, VS 2015 с С# 6, хотя ничто из этого не имеет значения.
Я попытался сделать образец с С# 5, но как только я заменил все "?". операторов, это прекращается.
Я организовал проект, чтобы люди могли сами попробовать:
git clone -b crash-sample https://github.com/jtheisen/moldinium.git
Я очистил и протестировал его на 4 машинах, все они показали тот же эффект.
Трассировка стека аварии:
Ex.: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at IronStone.Moldinium.LiveList.<>c__DisplayClass10_0`1.<Where>b__2(ListEvent`1 v)
at IronStone.Moldinium.ActionObserver`1.OnNext(T value) in C:\Source\Repos\moldinium\ConsoleApplication1\Rx.cs:line 51
...snipped...
Запуск PEVerify на выходе вызывает следующую ошибку:
[IL]: Ошибка: [C:\Source\Repos\moldinium\ConsoleApplication1\bin\Debug\Bad.exe: IronStone.Moldinium.LiveList + < > c__DisplayClass10_0`1 [TSource]:: b__2] [смещение 0x0000013B] Невозможно разрешить токен.
Удаление всех операторов ?.
из файла Select.cs устраняет проблему.
Используя ILSpy, я выделил проблему:
IronStone.Moldinium.LiveList.<>c__DisplayClass10_0`1.<Where>b__2
Вы можете увидеть IL Dumps метода (через ILSpy) в gist здесь. Bad IL при использовании ?.
Good IL - это стиль С# 5.0.
Это было построено с помощью VS2015.3
Версия CSC: Microsoft (R) Visual С# Компилятор версии 1.3.1.60616
Ответы
Ответ 1
Я не могу вам помочь, потому что это действительно ошибка. Но я могу довести вас до точки, где происходит ошибка, и это может помочь вам воспроизвести ошибку в нескольких строках кода.
namespace ElvisBugInNullableGenericStructWithNestedTypeParameter
{
struct MyGenericStruct<T> { }
class Program
{
static void Main() { }
void Test<T>()
{
Func<T, bool> func = (arg =>
{
MyGenericStruct<T>? v1 = null;
return v1?.ToString() == null;
});
}
}
}
Если я заменил MyGenericStruct<T>?
на MyGenericStruct<int>?
, он будет работать.
Проблема заключается в том, что по какой-то причине, когда мы используем внешнюю T
в nullable struct, а затем мы пытаемся использовать оператор Elvis ?
, тип неизвестен (не удается разрешить токен).
Обновление
Если вы хотите исправить свое дело, вам не нужно удалять весь оператор Элвиса, просто удалите их из действия Subscribe
в рамках метода public static ILiveList<TSource> Where<TSource>(this ILiveList<TSource> source, Func<TSource, Boolean> predicate)
.