繁体   English   中英

C# Equals() == 关于数字

[英]C# Equals() == about number

我尝试以下代码使用==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 ,在阅读了Here1Here2帖子后,我仍然不明白为什么==Equals结果不同,

在这 4 种关于数字的情况下, ==Equals背后的工作细节是什么?

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



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

双精度浮点数 <-> 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

MSDN

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

返回值:

类型:System.Boolean

如果 obj 和此实例是相同类型表示相同值,则为 true ; 否则为假。*

如果你这样做:

        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;
}

(int)2 == (double)2.0(float)2.0 == (double)2.0在编译时进行比较。 实际上,它不比较支持数据类型,而是比较编译器看到的值(因此2==2 )。 即便如此, float / int上的==也会进行隐式类型转换。

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.

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

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

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

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

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

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

您希望它给出 true,但类型检查条件先于值比较。

谢谢大家的回答,都是很好的资料,让我找到了每种类型的Equals方法Doc。

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

和等于方法 MSDN 链接: Double , Int32 , Float(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 中的定义函数,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.

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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