C#Equals()==关于数字

时间:2017-10-23 08:10:13

标签: c#

我尝试使用代码使用==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 )   );

结果:

true 
false
true 
false

int, double, float全部是ValueType,在阅读了帖子 Here1 Here2 之后,我仍然无法理解为什么==Equals结果不同,

这4个案例中==Equals背后的工作细节是什么?

(如果这个问题重复,请告诉我)



编辑: 4个更有趣的案例:

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< - >浮

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

6 个答案:

答案 0 :(得分:4)

来自MSDN

  

ValueType.Equals指示此实例和指定对象是否相等。

  

返回值:

     

类型:System.Boolean

     

如果obj和此实例属于同一类型代表相同值,则为;否则,假。*

如果你这样做:

        int a = 1;
        double b = a;
        bool check = a.Equals(b);

您正在调用此Equals的实现:

[__DynamicallyInvokable]
public override bool Equals(object obj)
{
  if (!(obj is int))
    return false;
  return this == (int) obj;
}

如果你这样做:

        int a = 1;
        int b = a;
        bool check = a.Equals(b);

你在呼唤另一个人:

[NonVersionable]
[__DynamicallyInvokable]
public bool Equals(int obj)
{
  return this == obj;
}

答案 1 :(得分:3)

在编译时比较

(int)2 == (double)2.0(float)2.0 == (double)2.0。实际上,它不会比较后备数据类型,而是比较编译器看到的值(因此2==2)。即使这样,== / float上的int也会进行隐式类型转换。

虽然Equals方法在运行时运行where types are different,因此该方法返回false

答案 2 :(得分:3)

(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.

请注意,在返回false的情况下,这是因为尽管存在int.Equals(int),但编译器无法调用它,因为没有从浮点类型到int的自动类型转换。

答案 3 :(得分:2)

==是一个运算符,编译器将首先应用隐式转换以在需要时扩展其中一个操作数。

1.0 == 1 => 1.0 == 1.0 => true

Equals()方法不会触发隐式转换,因此返回false。它也更昂贵,需要拳击操作。它检查的第一件事就是操作数是否属于同一类型。

(1.0).Equals(1) => Double(1.0).Equals(object(1)) => Double == Int32 => false

答案 4 :(得分:0)

作为普通数字,==比较值。使用.Equals方法时,它们被视为object的实例,因此.Equals将类型视为不同,条件失败。

您希望它给出true,但类型检查条件在值比较之前。

答案 5 :(得分:0)

感谢大家的回答,他们都是好的信息,让我找到每种类型的Equals方法文档。

在与==相关的所有情况下都是如此,与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

和equals方法MSDN链接:DoubleInt32Float(Single)

在方法描述中,Equals方法的格式均为:

public bool Equals(double obj)
public bool Equals(int obj)
public bool Equals(float obj)

所以我想在使用Equals时,首先会转换等待比较的值,关键点是是否可以转换类型而不会被截断或舍入。

这里对应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

编辑并纠正:

通过转到VS中的定义Funciton,True Case全部转到Equals(double/float/int obj),错误案例全部转到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.

所以我猜如果隐式转换失败,它会转到Equals(object obj)并在类型检查时变为false。