问题描述
考虑这段代码:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
int
和 short
都是基本类型,但与 ==
比较返回 true,而与 Equals
返回 false.
Both int
and short
are primitive types, but a comparison with ==
returns true and a comparison with Equals
returns false.
为什么?
推荐答案
简答:
平等是复杂的.
基元类型覆盖基本 object.Equals(object)
,如果装箱的 object
具有相同的 type 和值,则返回 true.(请注意,它也适用于可空类型;非空可空类型总是装箱到底层类型的实例.)
Primitives types override the base object.Equals(object)
and return true if the boxed object
is of the same type and value. (Note that it will also work for nullable types; non-null nullable types always box to an instance of the underlying type.)
由于 newAge
是一个 short
,它的 Equals(object)
方法只有在你传递一个装箱的 short时才返回 truestrong> 具有相同的值.你传递的是一个装箱的 int
,所以它返回 false.
Since newAge
is a short
, its Equals(object)
method only returns true if you pass a boxed short with the same value. You're passing a boxed int
, so it returns false.
相比之下,==
运算符被定义为采用两个 int
s(或 short
s 或 long
s).
当您使用 int
和 short
调用它时,编译器会将 short
隐式转换为 int
并进行比较结果 int
s 按值.
By contrast, the ==
operator is defined as taking two int
s (or short
s or long
s).
When you call it with an int
and a short
, the compiler will implicitly convert the short
to int
and compare the resulting int
s by value.
原始类型也有自己的 Equals()
方法,可以接受相同的类型.
如果你写age.Equals(newAge)
,编译器会选择int.Equals(int)
作为最佳重载,并隐式转换short
为int
.然后它将返回 true
,因为此方法只是直接比较 int
.
Primitive types also have their own Equals()
method that accepts the same type.
If you write age.Equals(newAge)
, the compiler will select int.Equals(int)
as the best overload and implicitly convert short
to int
. It will then return true
, since this method simply compares the int
s directly.
short
也有 short.Equals(short)
方法,但 int
不能隐式转换为 short
,所以你没有调用它.
short
also has a short.Equals(short)
method, but int
cannot be implicitly converted to short
, so you aren't calling it.
您可以强制它通过强制转换调用此方法:
You could force it to call this method with a cast:
Console.WriteLine(newAge.Equals((short)age)); // true
这将直接调用 short.Equals(short)
,无需装箱.如果age
大于32767,会抛出溢出异常.
This will call short.Equals(short)
directly, without boxing. If age
is larger than 32767, it will throw an overflow exception.
您也可以调用 short.Equals(object)
重载,但显式传递一个装箱对象,以便它获得相同的类型:
You could also call the short.Equals(object)
overload, but explicitly pass a boxed object so that it gets the same type:
Console.WriteLine(newAge.Equals((object)(short)age)); // true
与前面的替代方法一样,如果它不适合 short
,则会引发溢出.与之前的方案不同,它将short
装箱成一个对象,浪费时间和内存.
Like the previous alternative, this will throw an overflow if it doesn't fit in a short
.
Unlike the previous solution, it will box the short
into an object, wasting time and memory.
这是来自实际源代码的两个 Equals()
方法:
Here are both Equals()
methods from the actual source code:
public override bool Equals(Object obj) {
if (!(obj is Int16)) {
return false;
}
return m_value == ((Int16)obj).m_value;
}
public bool Equals(Int16 obj)
{
return m_value == obj;
}
延伸阅读:
请参阅 Eric Lippert.
这篇关于C# 中基元的 == 和 Equals() 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!