[英]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
,在閱讀了Here1和Here2帖子后,我仍然不明白為什么==
和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.