[英]C# Equals() == about number
I try following code use ==
and Equals
on number comparison:我尝试以下代码使用
==
和Equals
进行数字比较:
Console.WriteLine( (int)2 == (double)2.0 );
Console.WriteLine( ( (int)2 ).Equals( (double)2.0) );
Console.WriteLine((float)2.0 == (double)2.0);
Console.WriteLine( ( (float)2.0 ).Equals( (double)2.0 ) );
The result:结果:
true
false
true
false
int, double, float
are all ValueType
, after reading posts Here1 and Here2 , I still cannot understand why ==
and Equals
turns out different result, int, double, float
都是ValueType
,在阅读了Here1和Here2帖子后,我仍然不明白为什么==
和Equals
结果不同,
What is the working detail behind ==
and Equals
in these 4 cases about number?在这 4 种关于数字的情况下,
==
和Equals
背后的工作细节是什么?
(if this question is duplicate please tell me) (如果这个问题是重复的,请告诉我)
EDIT: 4 more interesting cases:编辑: 4个更有趣的案例:
double, float <-> int双精度浮点数 <-> int
Console.WriteLine((double)2.0 == (int)2); //True
Console.WriteLine(((double)2.0).Equals((int)2)); //True
Console.WriteLine((float)2.0 == (int)2.0); //True
Console.WriteLine(((float)2.0).Equals((int)2.0)); //True
double, int <-> float double, int <-> 浮点数
Console.WriteLine((double)2.0 == (float)2.0); //True
Console.WriteLine(((double)2.0).Equals((float)2.0)); //True
Console.WriteLine((int)2 == (float)2.0); //True
Console.WriteLine(((int)2).Equals((float)2.0)); //False
ValueType.Equals indicates whether this instance and a specified object are equal.
ValueType.Equals 指示此实例与指定对象是否相等。
and和
Return value:
返回值:
Type: System.Boolean
类型:System.Boolean
true if obj and this instance are the same type and represent the same value ;
如果 obj 和此实例是相同类型并表示相同值,则为 true ; otherwise, false.*
否则为假。*
If you do this:如果你这样做:
int a = 1;
double b = a;
bool check = a.Equals(b);
You are calling this implementation of Equals:您正在调用 Equals 的此实现:
[__DynamicallyInvokable]
public override bool Equals(object obj)
{
if (!(obj is int))
return false;
return this == (int) obj;
}
If you do this:如果你这样做:
int a = 1;
int b = a;
bool check = a.Equals(b);
You are calling this other:你称之为另一个:
[NonVersionable]
[__DynamicallyInvokable]
public bool Equals(int obj)
{
return this == obj;
}
(int)2 == (double)2.0
and (float)2.0 == (double)2.0
are compared at compile time. (int)2 == (double)2.0
和(float)2.0 == (double)2.0
在编译时进行比较。 Actually it doesn't compare the backing data types but the values as seen by the compiler (hence 2==2
).实际上,它不比较支持数据类型,而是比较编译器看到的值(因此
2==2
)。 And even then, the ==
on float
/ int
does an implicit type conversion.即便如此,
float
/ int
上的==
也会进行隐式类型转换。
The Equals
method though is ran on runtime, where types are different and hence the method returns false
. Equals
方法虽然在运行时运行, 其中类型不同,因此该方法返回false
。
(int)2 == (double)2.0 - True because the compiler promotes int to double when comparing via ==.
((int)2).Equals( (double)2.0) - False because this is calling int.Equals(object) and the types are different.
(float)2.0 == (double)2.0 - True because the compiler promotes float to double when comparing via ==.
((float)2.0).Equals((double)2.0) - False becaue this is calling float.Equals(object) and the types are different.
(double)2.0 == (int)2 - True because the compiler promotes int to double when comparing via ==.
((double)2.0).Equals((int)2) - True because there exists double.Equals(double) and the compiler
promotes the integer parameter 2 to double to call double.Equals(2.0).
(float)2.0 == (int)2.0 - True because the compiler promotes int to float when comparing via ==.
((float)2.0).Equals((int)2.0) - True because there exists float.Equals(float) and the compiler
promotes the integer parameter 2 to float to call float.Equals(2.0f).
(double)2.0 == (float)2.0) - True because the compiler promotes float to double when comparing via ==.
((double)2.0).Equals((float)2.0) - True because there exists double.Equals(double) and the compiler
promotes the float parameter 2.0f to double to call double.Equals(2.0).
(int)2 == (float)2.0 - True because the compiler promotes int to float when comparing via ==.
((int)2).Equals((float)2.0) - False because this is calling int.Equals(object) and the types are different.
Note that in the cases where false
is returned, it's because although int.Equals(int)
exists, the compiler cannot call it because there is no automatic type conversion from floating point types to int
.请注意,在返回
false
的情况下,这是因为尽管int.Equals(int)
存在,但编译器无法调用它,因为没有从浮点类型到int
自动类型转换。
The ==
is an operator and the compiler will first apply implicit conversions to widen one of the the operands when needed. ==
是一个运算符,编译器将首先应用隐式转换以在需要时扩展其中一个操作数。
1.0 == 1
=> 1.0 == 1.0
=> true
1.0 == 1
=> 1.0 == 1.0
=> true
The Equals() method does not trigger implicit conversion and so it returns false. Equals() 方法不会触发隐式转换,因此它返回 false。 It is also more expensive, requiring a boxing operation.
它也更昂贵,需要拳击操作。 And one of the first things it checks is if the operands are of the same type.
它检查的第一件事是操作数是否为相同类型。
(1.0).Equals(1)
=> Double(1.0).Equals(object(1))
=> Double == Int32
=> false
(1.0).Equals(1)
=> Double(1.0).Equals(object(1))
=> Double == Int32
=> false
As plain numbers, ==
compares the values.作为普通数字,
==
比较值。 When using the .Equals
method, they are treated as instances of object
and hence the .Equals
sees the types as different and the condition fails.使用
.Equals
方法时,它们被视为object
实例,因此.Equals
将类型视为不同并且条件失败。
You would expect it to give true, but the type checking condition precedes the value comparison.您希望它给出 true,但类型检查条件先于值比较。
Thanks for everyone's answer, they are all good informations, and make me find Equals
method Doc of each type.谢谢大家的回答,都是很好的资料,让我找到了每种类型的
Equals
方法Doc。
In all cases related to ==
are all true, and cases related to Equals
are:在所有与
==
相关的情况下都为真,与Equals
相关的情况是:
Console.WriteLine( ( (int)2 ).Equals( (double)2.0) ); //False
Console.WriteLine( ( (float)2.0 ).Equals( (double)2.0 ) ); //False
Console.WriteLine(((double)2.0).Equals((int)2)); //True
Console.WriteLine(((float)2.0).Equals((int)2.0)); //True
Console.WriteLine(((double)2.0).Equals((float)2.0)); //True
Console.WriteLine(((int)2).Equals((float)2.0)); //False
and equals method MSDN link: Double , Int32 , Float(Single)和等于方法 MSDN 链接: Double , Int32 , Float(Single)
In method description, Equals method are all in the format:在方法描述中,Equals 方法都是这样的格式:
public bool Equals(double obj)
public bool Equals(int obj)
public bool Equals(float obj)
So I guess when using Equals, the value wait to be compared will be first converted, and key point is whether the type can be converted without being truncated or rounded off.所以我猜在使用Equals的时候,等待比较的值会先被转换,关键是类型是否可以转换而不被截断或四舍五入。
Here correspond to 6 cases:这里对应6种情况:
// double cannot implicit convert to int -> F
Console.WriteLine( ( (int)2 ).Equals( (double)2.0) ); //False
// double cannot implicit convert to float -> F
Console.WriteLine( ( (float)2.0 ).Equals( (double)2.0 ) ); //False
// int can implicit convert to double -> T
Console.WriteLine(((double)2.0).Equals((int)2)); //True
// int can implicit convert to float -> T
Console.WriteLine(((float)2.0).Equals((int)2.0)); //True
// float can implicit convert to double -> T
Console.WriteLine(((double)2.0).Equals((float)2.0)); //True
// float cannot implicit convert to int -> F
Console.WriteLine(((int)2).Equals((float)2.0)); //False
Edit and Correct:编辑和更正:
By Go to Definition Funciton in VS, True Case all go to Equals(double/float/int obj)
, and the False Case all go to Equals(object obj)
, and in the description of Equals(object obj)
:通过转到 VS 中的定义函数,True Case 都转到
Equals(double/float/int obj)
,False Case 都转到Equals(object obj)
,在Equals(object obj)
的描述中:
Returns:
true if obj <is an instance of Int/Float/Double> and <equals the value> of this instance;
otherwise, false.
So I guess if the implicit conversion fail, it goes to Equals(object obj)
and get false when type checking.所以我猜如果隐式转换失败,它会转到
Equals(object obj)
并在类型检查时得到 false。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.