Why integer zero does not equal long zero?

后端 未结 6 715
天命终不由人
天命终不由人 2020-12-11 00:28

A strange piece of code I\'ve just discovered in C# (should also be true for other CLI languages using .NET\'s structs).



        
6条回答
  •  自闭症患者
    2020-12-11 01:09

    In general, Equals() methods are not supposed to return true for objects of different types.

    a.Equals(b) calls int.Equals(object), which can only return true for boxed Int32s:

    public override bool Equals(Object obj) { 
        if (!(obj is Int32)) {
            return false;
        }
        return m_value == ((Int32)obj).m_value; 
    }  
    

    b.Equals(a) calls long.Equals(long) after implicitly converting the int to a long.
    It therefore compares the two longs directly, returning true.

    To understand more clearly, look at the IL generated by this simpler example (which prints True False True):

    int a = 0;
    long b = 0L;
    
    Console.WriteLine(a == b);
    Console.WriteLine(a.Equals(b));
    Console.WriteLine(b.Equals(a));
    

    IL_0000:  ldc.i4.0    
    IL_0001:  stloc.0     
    IL_0002:  ldc.i4.0    
    IL_0003:  conv.i8     
    IL_0004:  stloc.1     
    
    IL_0005:  ldloc.0     //Load a
    IL_0006:  conv.i8     //Cast to long
    IL_0007:  ldloc.1     //Load b
    IL_0008:  ceq         //Native long equality check
    IL_000A:  call        System.Console.WriteLine    //True
    
    IL_000F:  ldloca.s    00            //Load the address of a to call a method on it
    IL_0011:  ldloc.1                   //Load b
    IL_0012:  box         System.Int64  //Box b to an Int64 Reference
    IL_0017:  call        System.Int32.Equals
    IL_001C:  call        System.Console.WriteLine    //False
    
    IL_0021:  ldloca.s    01  //Load the address of b to call a method on it
    IL_0023:  ldloc.0         //Load a
    IL_0024:  conv.i8         //Convert a to Int64
    IL_0025:  call        System.Int64.Equals
    IL_002A:  call        System.Console.WriteLine    //True
    

提交回复
热议问题