为什么在System.Double中重写==但在System.Int32中没有重写,这有什么后果?

时间:2014-04-21 19:56:14

标签: c# operator-overloading

在C#中为什么Double会覆盖==,但Int32却没有,影响是什么?

我看看msdn库。

我看到这个关于double的链接并没有多说here(虽然我理解double是Double对象的简写)..它没有显示方法例如..

但是System.Double上的这个链接确实提到了我正在寻找的内容here

它显示Equality运算符采用双精度数,因此过载。

图像对于MSDN中的Double,然后在方法之后(列出字段之前),它显示运算符,并显示等于运算符被覆盖

enter image description here

我可以点击"运营商"和it says

public static bool operator ==(
    double left,
    double right
)

而当我看System.Int32时 MSDN中的Int32图片位于

之下

enter image description here

请参阅该图片(System.Int32的页面),看起来==未被覆盖。

为什么,这有什么后果?

3 个答案:

答案 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,他们正在进行完全相同的比较,并且没有调用CompareToEquals(我认为实际发生了。我学到了一些东西!)。

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;
}

其他运营商遵循相同的模式,这很奇怪。也许是反编译错误?