虽然我们比较的是相同的值,但 .Net Equals() 返回不同的结果。有人可以向我解释为什么会这样吗?
class Program
{
static void Main(string[] args)
{
Int16 a = 1;
Int32 b = 1;
var test1 = b.Equals(a); //true
var test2 = a.Equals(b); //false
}
}
它与我们比较的类型范围有什么关系吗?
Int32
有一个 Equals(Int32)
重载和 Int16
可以隐式转换为等效的 Int32
。通过此重载,它现在正在比较两个 32 位整数,检查值是否相等,并自然返回 true
。
Int16
有自己的 Equals(Int16)
方法重载,但没有从 Int32
到 Int16
的隐式转换(因为您可以拥有超出 16 位整数范围的值)。因此类型系统忽略这个重载并恢复到 Equals(Object)
重载。其文档报告:
true if obj is an instance of Int16 and equals the value of this
instance; otherwise, false.
但是,我们传入的值虽然“等于此实例的值”(1 == 1
),但它不是Int16
因为它是 Int32
。
b.Equals(a)
的等效代码如下所示:
Int16 a = 1;
Int32 b = 1;
Int32 a_As_32Bit = a; //implicit conversion from 16-bit to 32-bit
var test1 = b.Equals(a_As_32Bit); //calls Int32.Equals(Int32)
现在很明显,我们将两个数字作为 32 位整数进行比较。
a.Equals(b)
的等效代码如下所示:
Int16 a = 1;
Int32 b = 1;
object b_As_Object = b; //treats our 16-bit integer as a System.Object
var test2 = a.Equals(b_As_Object); //calls Int16.Equals(Object)
现在很明显我们正在调用一个不同的相等方法。在内部,相等方法或多或少是这样做的:
Int16 a = 1;
Int32 b = 1;
object b_As_Object = b;
bool test2;
if (b_As_Object is Int16) //but it's not, it's an Int32
{
test2 = ((Int16)b_As_Object) == a;
}
else
{
test2 = false; //and this is where your confusing result is returned
}