簡體   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