Object.Equals(Object,Object)中的NullReferenceException

时间:2012-02-28 16:24:42

标签: c# nullreferenceexception ilgenerator object-equality

场合

我正在使用ILGenerator生成包装器。我使用Object.Equals(Object, Object)用于实现包装器字段的相等比较。调试器抛出NullReferenceException以及以下堆栈跟踪。

at System.Object.Equals(Object objA, Object objB)
at HIDDEN.StateTransitionWrapper.op_Equality(StateTransitionWrapper , StateTransitionWrapper )
at HIDDEN.StateTransitionWrapper.Equals(Object )
at System.Object.Equals(Object objA, Object objB)
at HIDDEN.StationEventCompositeWrapper.op_Equality(StationEventCompositeWrapper , StationEventCompositeWrapper )
at HIDDEN.StationEventCompositeWrapper.Equals(Object )
at System.Object.Equals(Object objA, Object objB)
at HIDDEN.CompareResult..ctor(Object object0, Object object1, String fieldName) 
....

Object.Equals(Object,Object) - 反汇编

public static bool Equals(object objA, object objB)
{
    return objA == objB || (objA != null && objB != null && objA.Equals(objB));
}

正如你在反汇编中看到的那样,任何NullReferenceException都不可能发生,因为它不会到达方法调用所在的部分。

可能出现的问题

正如我所说,使用ILGenerator生成孔代码,我认为这可能是错误的唯一可能来源。调用者只有里面的值类型,所以对象甚至不可能为null。

调用IL-Code

IL_0040: ldarg.0
IL_0041: call instance valuetype [HIDDEN]HIDDEN.StationStateType HIDDEN.StateTransitionWrapper::get_StationState()
IL_0046: box [mscorlib]System.Object
IL_004b: ldarg.1
IL_004c: call instance valuetype [HIDDEN]HIDDEN.StationStateType HIDDEN.StateTransitionWrapper::get_StationState()
IL_0051: box [mscorlib]System.Object
IL_0056: call bool [mscorlib]System.Object::Equals(object, object)

2 个答案:

答案 0 :(得分:3)

box指令不应该指定您要尝试的类型吗?

例如,你不应该使用......

box System.Int32  // or whatever

......而不是......

box System.Object

答案 1 :(得分:2)

typeTok 操作码(ECMA-355 Partition III,第4.2节)从堆栈中获取 val 并将其转换为 obj 。如果 typeTok 是引用类型,则box指令返回 val 未更改 [强调添加]为 obj 。当 typeTok 是值类型(至少是不可为空的)时,box会创建一个新对象并从 val 复制数据进入新的对象。

正如@LukeH指出的那样,上面的IL正在使用命令box [mscorlib]System.Object,它应该使用box [HIDDEN]HIDDEN.StationStateType。后者仍将返回object,该Object.Equals(Object, Object)NullReferenceException电话有效。我相信当前调用返回的是导致{{1}}的无效对象。