在C#中为什么Double
会覆盖==
,但Int32
却没有,影响是什么?
我看看msdn库。
我看到这个关于double的链接并没有多说here(虽然我理解double是Double
对象的简写)..它没有显示方法例如..
但是System.Double
上的这个链接确实提到了我正在寻找的内容here
它显示Equality运算符采用双精度数,因此过载。
图像对于MSDN中的Double
,然后在方法之后(列出字段之前),它显示运算符,并显示等于运算符被覆盖
我可以点击"运营商"和it says
public static bool operator ==(
double left,
double right
)
而当我看System.Int32
时
MSDN中的Int32
图片位于
请参阅该图片(System.Int32
的页面),看起来==
未被覆盖。
为什么,这有什么后果?
答案 0 :(得分:3)
一个可能的原因是因为Double.NaN。
对于== operator:MSDN说:如果使用等于运算符(==)测试两个Double.NaN值的相等性,则结果为false;两个Double.NaN值不相等。如果通过调用Equals方法测试它们的相等性,则结果为true。当您想确定Double的值是否不是数字(NaN)时,另一种方法是调用IsNaN方法。
所以==运算符和Double的Equals方法对Double.NaN有不同的行为,我认为这就是为什么==覆盖double。至于int,没有这种特殊情况。
演示差异的代码:
using System;
public class Example
{
public static void Main()
{
Console.WriteLine("NaN == NaN: {0}", Double.NaN == Double.NaN);
Console.WriteLine("NaN != NaN: {0}", Double.NaN != Double.NaN);
Console.WriteLine("NaN.Equals(NaN): {0}", Double.NaN.Equals(Double.NaN));
Console.WriteLine("! NaN.Equals(NaN): {0}", ! Double.NaN.Equals(Double.NaN));
Console.WriteLine("IsNaN: {0}", Double.IsNaN(Double.NaN));
Console.WriteLine("\nNaN > NaN: {0}", Double.NaN > Double.NaN);
Console.WriteLine("NaN >= NaN: {0}", Double.NaN >= Double.NaN);
Console.WriteLine("NaN < NaN: {0}", Double.NaN < Double.NaN);
Console.WriteLine("NaN < 100.0: {0}", Double.NaN < 100.0);
Console.WriteLine("NaN <= 100.0: {0}", Double.NaN <= 100.0);
Console.WriteLine("NaN >= 100.0: {0}", Double.NaN > 100.0);
Console.WriteLine("NaN.CompareTo(NaN): {0}", Double.NaN.CompareTo(Double.NaN));
Console.WriteLine("NaN.CompareTo(100.0): {0}", Double.NaN.CompareTo(100.0));
Console.WriteLine("(100.0).CompareTo(Double.NaN): {0}", (100.0).CompareTo(Double.NaN));
}
}
// The example displays the following output:
// NaN == NaN: False
// NaN != NaN: True
// NaN.Equals(NaN): True
// ! NaN.Equals(NaN): False
// IsNaN: True
//
// NaN > NaN: False
// NaN >= NaN: False
// NaN < NaN: False
// NaN < 100.0: False
// NaN <= 100.0: False
// NaN >= 100.0: False
// NaN.CompareTo(NaN): 0
// NaN.CompareTo(100.0): -1
// (100.0).CompareTo(Double.NaN): 1
代码也来自MSDN
答案 1 :(得分:1)
Int32
在.NET方面似乎非常特殊。源代码中缺少的功能很可能被烘焙到系统的核心。
如果不在结构中声明这些运算符,则无法将结构/值类型与==
,>
等进行比较。因为Int32
遗漏了这些,所以我得出了上面的结论。
做一个简单的测试并转储IL,他们正在进行完全相同的比较,并且没有调用CompareTo
或Equals
(我认为实际发生了。我学到了一些东西!)。
public void TestInts()
{
var x = 1;
var y = 2;
var equals = x == y;
}
.method public hidebysig
instance void TestInts () cil managed
{
// Method begins at RVA 0x2094
// Code size 11 (0xb)
.maxstack 2
.locals init (
[0] int32 x,
[1] int32 y,
[2] bool equals
)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.i4.2
IL_0004: stloc.1
IL_0005: ldloc.0
IL_0006: ldloc.1
IL_0007: ceq
IL_0009: stloc.2
IL_000a: ret
}
public void TestDoubles()
{
var x = 1.7d;
var y = 1.5d;
var equals = x == y;
}
.method public hidebysig
instance void TestDoubles () cil managed
{
// Method begins at RVA 0x20ac
// Code size 27 (0x1b)
.maxstack 2
.locals init (
[0] float64 x,
[1] float64 y,
[2] bool equals
)
IL_0000: nop
IL_0001: ldc.r8 1.7
IL_000a: stloc.0
IL_000b: ldc.r8 1.5
IL_0014: stloc.1
IL_0015: ldloc.0
IL_0016: ldloc.1
IL_0017: ceq
IL_0019: stloc.2
IL_001a: ret
}
上述IL只有两种情况都需要标准ceq
opcode。根据.NET标准,Int32
应该在源代码中声明比较运算符,但事实并非如此。
编辑:好像所有整数值类型都是这样的。 Single,Double,Decimal都具有源代码中指定的运算符。 Int16,Int32,Int64,Byte,不要。
答案 2 :(得分:-1)
使用ILSpy我可以看到Double.Equals
有一些额外的逻辑来检查被比较的值是否为NaN。
ILSpy还将==
的主体反编译为:
public static bool operator ==(double left, double right)
{
return left == right;
}
其他运营商遵循相同的模式,这很奇怪。也许是反编译错误?