看似相同的原始值不相等

时间:2018-02-07 11:03:48

标签: c# casting equality primitive

出现了一个奇怪的案例。两个对象的两个属性被转换为相同的基元类型,并且(看似)具有相同的值。但是,相等比较器返回false。如果我们使用Equals方法(或其他比较两个值的方法),那么我们会得到正确的结果。

更奇怪的是,实际上将演员表的结果放入一个新变量似乎也有效。

下面是一个非常简化的代码示例,并且 NOT 在复制和编译时会产生相同的结果。它仅用于说明问题发生的一般设置。

class Program
{
    static void Main(string[] args)
    {
        var v1 = new Object1 { SomeValue = (short)-1d };

        var invalidResult = (int)v1.SomeValue == (int)SomeEnum.Value1;     //for some reason this returns false
        var validResult = ((int)v1.SomeValue).CompareTo((int)SomeEnum.Value1) == 0;    //this works
        var extraValidResult = ((int)v1.SomeValue).Equals((int)SomeEnum.Value1);
        var cast1 = (int)v1.SomeValue;
        var cast2 = (int)SomeEnum.Value1;
        var otherValidResult = cast1 == cast2;                          //this also works
    }
}

public class Object1
{
    public short SomeValue { get; set; }
}

public enum SomeEnum : short
{
    Value1 = -1,
    Value2 = 0,
    Value3 = 1
}

这是VS观察窗口的屏幕截图,作为我们所看到的内容的证据:

Proof

我知道有时VS会在“监视”窗口中显示无效值,但是效果不仅限于该窗口,并且案例实际上未通过if检查它在我们的某个测试中不应该出现的位置。 AFAIK代码中没有诡计(如覆盖==Equals)。

这里可能会发生什么?

(我们显然已经使用CompareTo方法“修复”了这个问题,但我们仍然在想知道到底发生了什么...... ...

编辑:
我意识到上面的代码示例......有点无用。但是,发布有问题的实际代码可能会非常困难;有很多。最后,一些对象的“实时”值从SQL服务器(使用实体框架)填充,这进一步使代码共享变得复杂。我很乐意尝试回答任何其他问题以尝试缩小问题范围,但遗憾的是,不可能共享完整代码(特定的代码块可能,但由于显而易见的原因无法编译) 。提供示例代码是为了表明问题有多奇怪。

编辑2:
抱歉耽搁了。这是有问题的特定方法:

public bool IsLocalizationBlockedByMagPElem(int localizationId)
{
    IEnumerable<MagPElem> magPElems = MagPElemRepository.GetByLocalizationIdAndStatusesOrderedByIdDescThenSubLpAsc(localizationId, DocumentStatus.InBuffer, DocumentStatus.InBufferReedition);

    if (magPElems.Count() != 0)
    {
        var magPElem = magPElems.First();
        //this commented out code did not return the expected value due to the strange comparison issue
        //return (magPElem.MaP_GIDTyp == (int)ExternalSystemType.PM_GIDTyp || (magPElem.MaP_GIDTyp == (int)ExternalSystemType.MP_GIDTyp && magPElem.MaP_SubGIDLp == (short)LocalizationDirection.Destination));
        //to avoid the issue CompareTo is being used, but Equals would work just as well
        return (magPElem.MaP_GIDTyp == (int)ExternalSystemType.PM_GIDTyp || (magPElem.MaP_GIDTyp == (int)ExternalSystemType.MP_GIDTyp && magPElem.MaP_SubGIDLp.CompareTo((short)LocalizationDirection.Destination) == 0));
    }
    return false;
}

我还更新了屏幕截图以包含更多屏幕。在屏幕截图中,上面的代码存在一些细微的差异,因为我们正在测试以查看正在发生的事情(例如尝试不同的强制转换或将转换结果分配给变量)。但问题的关键在那里。

0 个答案:

没有答案