为什么在.NET 4下运行时此行会导致VerificationException?

Lil*_*ver 19 .net c# .net-4.0 peverify

帮帮我吧 - 为什么这个代码在.NET 4.0下运行时会导致VerificationException?

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;
}
Run Code Online (Sandbox Code Playgroud)

我跑peverify了.net 2.0程序集并收到以下消息:

ImageResizer.Util.Utils :: parseEnum [T]] [offset 0x0000000A]调用的'this'参数必须是调用方法的'this'参数.

这会VerificationException: Operation could destabilize the runtime在中等信任下运行代码时导致消息.

我已经阅读了所有关于堆栈溢出的类似帖子,并且它们都不适用于此代码.

是否有一些新的泛型会导致此代码无效?

por*_*ges 32

错误的根本原因是IsEnum签名的变化.

在.NET 2.0(和3.0)中,IsEnum 不是虚方法:

public bool IsEnum { get; }
Run Code Online (Sandbox Code Playgroud)

发出调用它的程序集是:

call instance bool [mscorlib]System.Type::get_IsEnum()
Run Code Online (Sandbox Code Playgroud)

在.NET 4.0中,IsEnum 是一个虚方法:

public virtual bool IsEnum { get; }
Run Code Online (Sandbox Code Playgroud)

这是4.0的组装线:

callvirt instance bool [mscorlib]System.Type::get_IsEnum()
Run Code Online (Sandbox Code Playgroud)

您获得的错误是在2.0版本之前的peverify添加的,并在非虚拟地调用虚拟方法时发出警告.

现在,peverify加载代码,加载.NET 4.0,然后检查代码.由于您的代码非虚拟地调用(.NET 4.0)虚拟方法,因此会显示错误.

有人会认为,因为你正在构建.NET 2.0版本,这应该没问题,并且它会加载.NET 2.0 CLR来检查.它似乎并非如此.

编辑:

为了检查这一点,我下载了.NET 2.0的SDK并尝试了peverify在那里.它正确验证了代码.

所以消息似乎是这样的:使用peverify与代码的目标框架匹配的a .

解:

似乎_Type界面提供了一个解决方案:

if (((_Type)typeof(T)).IsEnum) ...
Run Code Online (Sandbox Code Playgroud)

文档说它是为从非托管代码调用而设计的,但作为一个接口的副作用,它提供了一个稳定(虚拟)的方法来调用.

我已经确认它适用于peverify您是2.0还是4.0.

  • 很棒的答案!我喜欢学习这样的东西. (4认同)