I try following code use ==
and Equals
on number comparison:
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,
What is the working detail behind ==
and Equals
in these 4 cases about number?
(if this question is duplicate please tell me)
EDIT: 4 more interesting cases:
double, float <-> 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
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
From MSDN :
ValueType.Equals indicates whether this instance and a specified object are equal.
and
Return value:
Type: System.Boolean
true if obj and this instance are the same type and represent the same value ; otherwise, false.*
If you do this:
int a = 1;
double b = a;
bool check = a.Equals(b);
You are calling this implementation of 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. Actually it doesn't compare the backing data types but the values as seen by the compiler (hence 2==2
). And even then, the ==
on float
/ int
does an implicit type conversion.
The Equals
method though is ran on runtime, where types are different and hence the method returns 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
.
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
The Equals() method does not trigger implicit conversion and so it returns 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
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.
You would expect it to give true, but the type checking condition precedes the value comparison.
Thanks for everyone's answer, they are all good informations, and make me find Equals
method Doc of each type.
In all cases related to ==
are all true, and cases related to Equals
are:
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)
In method description, Equals method are all in the format:
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.
Here correspond to 6 cases:
// 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)
:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.