的问题是在ParameterBuilder.SetConstant
,不Activator.CreateInstance
。 SetConstant
是用于定义可选参数的默认值的函数,并且要求提供具体值作为常数。对于裁判班,null
是一个有效的具体价值,但对于之前创造Nullable<>
值类,null
不是有效的值。例如,如何将null
解锁为int
?所以SetConstant
检查值类型,看看是否传入的恒定具体值是null
并引发ArgumentException
为更具描述性的错误比NullReferenceException
那么得到的拆箱空成值类。
对于Nullable<>
,null
现在是值类的有效具体值。 Nullable<>
本身是一个值类,如Activator.CreateInstance
,和取消装箱null
看出成Nullable<int>
具有含义。这是SetConstant
有一个错误:它没有考虑到这一点,并抛出一个“描述性”的错误。代替来自Microsoft的错误修正,任何对SetConstant
的调用Nullable<>
将不得不实施由不正确的条件保护的行为。这意味着使用反射挖掘ParameterBuilder
的私有方法和字段。这里是我编写的代码只是这种情况。标准SetConstant
函数应该用于不能显示错误的情况。
//ModuleBuilder module : a parameter passed into the containing function, the module which is being built (which contains the method that has the optional parameter we are setting the constant for)
//ParameterBuilder optParam : A parameter passed into the containing function, the parameter that is being built which is to have the null default value.
MethodInfo method = typeof(TypeBuilder).GetMethods(BindingFlags.Static | BindingFlags.NonPublic)
.Where(m => m.Name == "SetConstantValue" && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.Name == "RuntimeModule")
.Single();
var RuntimeHandle = typeof(ModuleBuilder).GetMethod("GetNativeHandle", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(null, new object[]
{
RuntimeHandle.Invoke(module, new object[]{}),
optParam.GetToken().Token,
0x12,
null
});
我向微软报告了这个错误。他们回应说,它不会在.NET 3.5中修复,但它被添加到内部错误数据库中。
UPDATE:
该bug已被固定在.NET 4.0。 ParameterBuilder.SetConstant
现在有一个跳转到constant == null
的条件,该条件用于检查值类型是否是从Nullable<>
派生的通用类型,如果不是,则仅引发该异常。
模块和optParam指的是什么? – 2014-01-15 04:52:22
1.非常疯狂的黑客攻击。 2.对象形式中的可空对象是空的 - 这是通过设计。 3.更多描述请。 – Vlad 2016-03-09 09:31:11
是的,这是一个疯狂的黑客攻击。这是为了解决'ParameterBuilder.SetConstant'具有'if(value == null)抛出新的ArgumentException(...)'。 “ParameterBuilder.SetConstant”使用的实际本地代码(这是私有的,以及我在上面反映的)可以使用Nullables为空,因为它是有设计的。它只是一个包含错误的托管,面向公众的功能,并且需要绕过。这个错误已经被修复,所以这个答案不再是必须的,除非你的目标是3.5或更低。 – 2016-05-31 18:09:04