[英]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.