Подтвердить что ты не робот

Почему эта строка вызывает проверку VerificationException при работе в .NET 4?

Помогите мне - почему этот код вызывает VerificationException при запуске под .NET 4.0?

public  T parseEnum<T>(string value, T defaultValue) {
  //Removing the following lines fixes the problem
  if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
  return defaultValue;
}

Я запустил peverify на сборке .net 2.0 и получил следующее сообщение:

ImageResizer.Util.Utils:: parseEnum [T]] [offset 0x0000000A] Параметр 'this' для вызова должен быть параметром вызывающего метода 'this'.

Это вызывает сообщение VerificationException: Operation could destabilize the runtime при запуске кода под средним доверием.

Я уже прочитал все похожие сообщения о переполнении стека, и ни один из них не применим к этому коду.

Есть ли что-то новое с дженериками, которые могут привести к тому, что этот код будет каким-то образом недействительным?

4b9b3361

Ответ 1

Основной причиной ошибки является изменение в сигнатуре IsEnum.

В .NET 2.0 (и 3.0) IsEnum не был виртуальным методом:

public bool IsEnum { get; }

Узел, испущенный для вызова:

call instance bool [mscorlib]System.Type::get_IsEnum()

В .NET 4.0 IsEnum - это виртуальный метод:

public virtual bool IsEnum { get; }

Вот такая же строка сборки для 4.0:

callvirt instance bool [mscorlib]System.Type::get_IsEnum()

Ошибка, которую вы получаете, была добавлена ​​в peverify непосредственно перед выпуском 2.0 и предупреждает, что виртуальный метод называется не виртуальным.

Теперь peverify загружает ваш код, загружает .NET 4.0, а затем проверяет ваш код. Поскольку ваш код вызывает виртуальный метод (.NET 4.0) практически без изменений, отображается ошибка.

Можно подумать, что, поскольку вы строите против версии .NET 2.0, это должно быть хорошо, и он будет загружать CLR.NET 2.0 для проверки. Это не похоже.

Edit:

Чтобы проверить это, я скачал .NET 2.0 SDK и попробовал peverify там. Он корректно проверяет код.

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

Решение:

Кажется, что _Type интерфейс предлагает следующее:

if (((_Type)typeof(T)).IsEnum) ...

В документации говорится, что он предназначен для вызова из неуправляемого кода, но в качестве побочного эффекта его является интерфейсом, он обеспечивает стабильный (виртуальный) метод для вызова.

Я подтвердил, что он работает с peverify, если вы нацеливаете 2.0 или 4.0.