我在C#中发现的一段奇怪的代码(对于使用.NET的其他CLI语言也应如此structs).
using System;
public class Program
{
public static void Main(string[] args)
{
int a;
long b;
a = 0;
b = 0;
Console.WriteLine(a.Equals(b)); // False
Console.WriteLine(a.Equals(0L)); // False
Console.WriteLine(a.Equals((long)0)); // False
Console.WriteLine(a.Equals(0)); // True
Console.WriteLine(a.Equals(a)); // True
Console.WriteLine(a == b); // True
Console.WriteLine(a == 0L); // True
Console.WriteLine();
Console.WriteLine(b.Equals(a)); // True
Console.WriteLine(b.Equals(0)); // True
Console.WriteLine(b.Equals((int)0)); // True
Console.WriteLine(b.Equals(b)); // True
Console.WriteLine(b == a); // True
Console.WriteLine(b == 0); // True
}
}
Run Code Online (Sandbox Code Playgroud)
这里有两个有趣的点(假设a是int和b是long):
a != b,但是b == a;(a.Equals(b)) != (a == b)是否有任何理由以这种方式实施比较?
注意:如果它有任何区别,则使用.NET 4.
SLa*_*aks 27
通常,Equals()对于不同类型的对象,方法不应返回true.
a.Equals(b)调用int.Equals(object),只能为盒装Int32s 返回true :
public override bool Equals(Object obj) {
if (!(obj is Int32)) {
return false;
}
return m_value == ((Int32)obj).m_value;
}
Run Code Online (Sandbox Code Playgroud)
b.Equals(a)long.Equals(long)隐式转换int为a 后调用long.
因此它long直接比较两个s,返回true.
为了更清楚地理解,请查看由这个更简单的示例生成的IL(打印True False True):
int a = 0;
long b = 0L;
Console.WriteLine(a == b);
Console.WriteLine(a.Equals(b));
Console.WriteLine(b.Equals(a));
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)