A strange piece of code I\'ve just discovered in C# (should also be true for other CLI languages using .NET\'s structs).
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