Вы нашли ошибку генерации кода в джиттере .NET 4 x86. Это очень необычный вариант, он дает сбой только тогда, когда код не оптимизирован. Машинный код выглядит так:
State a = s[0, 0];
013F04A9 push 0 ; index 2 = 0
013F04AB mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04AE xor edx,edx ; index 1 = 0
013F04B0 call 013F0058 ; eax = s[0, 0]
013F04B5 mov dword ptr [ebp-4Ch],eax ; $temp1 = eax
013F04B8 movsx eax,byte ptr [ebp-4Ch] ; convert sbyte to int
013F04BC mov dword ptr [ebp-44h],eax ; a = s[0, 0]
Console.WriteLine(a == s[0, 0]); // False
013F04BF mov eax,dword ptr [ebp-44h] ; a
013F04C2 mov dword ptr [ebp-50h],eax ; $temp2 = a
013F04C5 push 0 ; index 2 = 0
013F04C7 mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04CA xor edx,edx ; index 1 = 0
013F04CC call 013F0058 ; eax = s[0, 0]
013F04D1 mov dword ptr [ebp-54h],eax ; $temp3 = eax
; <=== Bug here!
013F04D4 mov eax,dword ptr [ebp-50h] ; a == s[0, 0]
013F04D7 cmp eax,dword ptr [ebp-54h]
013F04DA sete cl
013F04DD movzx ecx,cl
013F04E0 call 731C28F4
Дела с большим количеством временных и дублирующих кодов, это нормально для неоптимизированного кода. Команда на 013F04B8 заслуживает внимания, именно здесь происходит необходимое преобразование из sbyte в 32-разрядное целое число. Вспомогательная функция получения массива вернула 0x0000000FF, равный State.BUG, и его необходимо преобразовать в -1 (0xFFFFFFFF), прежде чем можно будет сравнить значение. Инструкция MOVSX является инструкцией Sign eXtension.
То же самое происходит снова в 013F04CC, но на этот раз нет инструкции MOVSX для того же преобразования. Вот где чипы падают, инструкция CMP сравнивает 0xFFFFFFFF с 0x000000FF, и это ложно. Так что это ошибка пропуска, генератор кода не смог снова сгенерировать MOVSX для выполнения того же преобразования sbyte в int.
Что особенно необычно в этой ошибке, так это то, что она работает правильно, когда вы включаете оптимизатор, теперь он знает, что нужно использовать MOVSX в обоих случаях.
Вероятная причина, по которой эта ошибка так долго не обнаруживалась, - использование sbyte в качестве базового типа перечисления. Довольно редко, чтобы сделать. Также полезно использовать многомерный массив, комбинация фатальна.
В противном случае я бы сказал, что это довольно критическая ошибка. Трудно догадаться, насколько широко это может быть, у меня есть только джиттер 4.6.1 x86 для тестирования. X64 и 3.5 x86 jitter генерируют совершенно другой код и избегают этой ошибки. Временный обходной путь для продолжения работы состоит в том, чтобы удалить sbyte в качестве базового типа enum и оставить его по умолчанию int , поэтому расширение знака не требуется.
Вы можете отправить сообщение об ошибке по адресу connect.microsoft.com, ссылки на этот вопрос достаточно для того, чтобы рассказать им все, что им нужно знать. Дайте мне знать, если вы не хотите уделять время, и я позабочусь об этом.