提问人:MBender 提问时间:2/7/2018 最后编辑:MBender 更新时间:2/7/2018 访问量:113
看似相同的基元值并不相等
Seemingly identical primitive values aren't equal
问:
一个奇怪的案例突然出现。两个对象的两个属性被强制转换为相同的基元类型,并且(似乎)具有相同的值。但是,相等比较器返回 。如果我们使用该方法(或其他比较两个值的方法),那么我们会得到正确的结果。false
Equals
更奇怪的是,实际上将强制转换的结果放入一个新变量中似乎也有效。
下面是一个非常简化的代码示例,在复制和编译时不会产生相同的结果。它只是用于说明发生问题的一般设置。
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 监视窗口的屏幕截图,作为我们所看到的内容的证明:
我知道有时 VS 可以在“监视”窗口中显示无效值,但效果不仅限于该窗口,而且在我们的一个测试中,案例实际上未能通过检查,而它不应该检查。AFAIK 代码中没有诡计(如覆盖或 )。if
==
Equals
这里可能发生了什么?
(我们显然已经使用该方法“修复”了问题,但我们仍然在挠头,想知道到底发生了什么......CompareTo
编辑:
我意识到上面的代码示例是......有点没用。但是,发布有问题的实际代码可能被证明是非常困难的;有很多。最后,某些对象的“实时”值是从 SQL Server(使用实体框架)填充的,这会使代码共享更加复杂。我很乐意尝试回答任何其他问题以尝试缩小问题范围,但不幸的是,共享完整代码是不可能的(它的特定块是可能的,但由于显而易见的原因它不会编译)。提供了示例代码以显示该问题有多奇怪。
编辑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;
}
我还更新了校样屏幕截图,以包含更多屏幕。在屏幕截图中,与上述代码存在一些细微的差异,因为我们正在测试以查看发生了什么(例如尝试不同的强制转换或将强制转换结果分配给变量)。但问题的要点就在那里。
答: 暂无答案
评论
LocalizationDirection.Destination
mapPElem.MaP_SubGIDLp
(int)v1.SomeValue == (int)SomeEnum.Value1