简体   繁体   English

C# Equals() == 关于数字

[英]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 ,在阅读了Here1Here2帖子后,我仍然不明白为什么==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

From MSDN :MSDN

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM