我今天遇到了这个有趣的情况:
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#编译器会秘密地将整数转换为double,并且通过使用Object intermediate,编译器没有足够的信息来执行此操作
我的问题是,运行时是否有足够的信息将整数提升到两倍以进行比较?如果C#编译器假定它有足够的理由进行隐式转换,为什么JIT不应该有类似的行为呢?
答案 0 :(得分:4)
C#必须像语言规范所说的那样工作。这与Jitter无关,它只需要实现语言规范。
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
它确实有一些与您的问题相关的细节,因此值得一读。
答案 1 :(得分:2)
C#是一种特定的编程语言,具有处理2.0 == 2
的特定语义,在ECMA-334标准中定义。公共语言运行时(CLR)是由ECMA-335标准定义的执行环境,对字节码而不是C#源代码进行操作。它们的语义在很多方面都有所不同,所以虽然运行时部分可以实现为自动执行这些类型的比较的扩展转换,但实际上并没有 方式。
这里完成的具体比较恰好是调用Double.Equals(Object)
,它返回
true
如果 obj 是Double
的实例并且等于此实例的值;否则,错误。
答案 2 :(得分:0)
这更像是一个社区问题而不是寻找特定解决方案的人。但我很乐意减肥。
首先,我首先要说双重平等比较已经很危险,因为我相信你可能知道。
的主题有很多信息if(doubleNum == doubleNum2)
还要考虑两个不是亲戚的不同类型的对象应该是等同的吗?在编写代码时,编译器可以假设一些基本的想法。但是大多数.Equals(对象)方法所做的第一件事是检查类型兼容性,如果它们不兼容,则返回false。我假设这是这里的情况,因为b.Equals(2)假设传递的int类型不是双精度。
在查看double.Equals(object)方法之后,你会注意到它做的第一件事就是检查传递的对象是否为double。由于它是Int32,函数返回false。
虽然其他答案更多的原因是实施的原因。以上内容应解释为什么运行时表现如何。