2011-08-02 48 views
17

帮我解决问题 - 为什么在.NET 4.0下运行时,这段代码会导致一个VerificationException?为什么这行在.NET 4下运行时会导致一个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; 
} 

我在.NET 2.0组件跑peverify并得到以下信息:

ImageResizer.Util.Utils :: parseEnum [T]] [偏移0X0000000A]的 '这' 参数来该调用必须是调用方法的'this'参数。

这将导致在中等信任下运行代码时发出VerificationException: Operation could destabilize the runtime消息。

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

是否有什么新的泛型会导致此代码在某种程度上无效?

+0

我只是运行这个代码,并没有收到这样的例外。你确定这是错误所在吗?这是在asp中使用吗? –

+0

您是否使用Visual Studio或其他编译器(如Mono)生成.NET程序集? – Jacob

+1

错误消息向我表明它位于正在发生此问题的呼叫地点(即您调用方法的地方)。你能向我们展示那些代码吗? –

回答

31

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

在.NET 2.0(和3.0),IsEnum wasn't a virtual method

public bool IsEnum { get; } 

发出调用它的组件是:

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

在.NET 4.0,IsEnum is a virtual method

public virtual bool IsEnum { get; } 

这里是4.0的组装线:

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

您遇到的错误是added in peverify just before the 2.0 release,并且在虚拟方法被称为非虚拟方法时发出警告。

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

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

编辑:

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

所以消息看起来是这样的:使用一个peverify它匹配您的代码的目标框架。

解决方案:

看来,_Type interface提供了一个解决这个:

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

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

我确定它可以与peverify一起使用,无论您的目标是2.0还是4.0。

+4

梦幻般的答案!我喜欢学习这样的事情。 –

+0

谢谢 - 这是有道理的。我的程序集都是针对.NET 2.0和.NET 4.0框架的,所以我想我根本无法调用IsEnum,对吗? –

+1

实际上,有一个'_Type'接口说它是“版本无关的”。它可能已被设计为解决这样的问题。我会将其添加到答案中。 – porges

相关问题