为什么整型在作为对象进行比较时不被提升为双精度?

本文关键字:双精度 整型 对象 为什么 比较 | 更新日期: 2023-09-27 18:14:48

我今天偶然发现了这个有趣的情况:

var a = new HashSet<Object> { 1.0, 2.0, 3.0 };
a.Contains(1);     //False
a.Contains(1.0);   //True

当然,这只是这个的一般版本:

Object b = 2.0;
b.Equals(2);            //False
b.Equals(2.0);          //True

我意识到这样做的原因是因为如果我写2.0 == 2, c#编译器秘密地插入从整数到双精度的强制转换,并且通过使用Object中间,编译器没有足够的信息来做这件事。

我的问题是,运行时没有足够的信息来将整数提升为双精度进行比较吗?如果c#编译器认为需要隐式转换,JIT为什么不能有类似的行为呢?

为什么整型在作为对象进行比较时不被提升为双精度?

c#必须按照语言规范规定的方式工作。这与抖动无关,它只需要实现语言规范。

c#语言规范说明了==必须如何工作。

CLR规范说明了Equals()必须如何工作。

在。net 1.1和。net 2.0之间有一个有趣的变化。

. net 1.1中,3f.Equals(3) == false .

在。net 2.0中,3f.Equals(3) == true.

这与Equals()对象比较版本不同。这说明了这种事情是多么微妙。

一个有趣的(但很老的)博客:http://blogs.msdn.com/b/jmstall/archive/2005/03/23/401038.aspx

它确实有一些与你的问题相关的细节,所以值得一读。

c#是一种特定的编程语言,具有处理2.0 == 2的特定语义,在ECMA-334标准中定义。公共语言运行时(CLR)是一个由ECMA-335标准定义的执行环境,它在字节码上运行,而不是c#源代码。它们的语义在许多方面有所不同,因此,虽然运行时部分可以实现为这些类型的比较自动执行扩展转换,但如果实际上没有这样做。

这里的比较恰好调用了Double.Equals(Object),它返回

true if objDouble的一个实例并且等于这个实例的值;否则,假的。

这更像是一个社区问题,而不是一个寻找特定解决方案的问题。不过我很乐意帮忙。

首先,我想说双等号比较已经很危险了,我相信你可能知道。有很多关于

的信息
if(doubleNum == doubleNum2)

还要考虑两个不同类型的非亲属对象是否可以相等?在编写代码时,编译器可以假设一些基本思想。但是大多数. equals (object)方法做的第一件事是检查类型兼容性,如果它们不兼容则返回false。我假定这里就是这种情况,因为b.Equals(2)假定传递的是int类型,而不是double类型。

看完double. equals (object)方法后,你会注意到它做的第一件事是检查传递的对象是否是双精度类型。由于是Int32类型,该函数返回false。

而其他答案更多的是实现是这样的原因。以上应该可以解释为什么运行时的行为是这样的。