objA == objB
和 objA.Equals(objB)
是否等价
先问大家一个问题:objA == objB
和 objA.Equals(objB)
是否等价?答案显然是要看具体情况,或者说很可能是不等价的。
可是如果我这么问呢?
对于定义float A, B;
A == B 是否应该和 A.Equals(B)完全等价呢?应该是的吧?也许大家的答案有下列几个之一:
- Equals通常用于在==运算符重载的时候,比较引用是否相等。
- Equals通常用于比较引用类型的引用是否相等。
float没有运算符重载,也不是一个引用类型,甚至我也看不出有什么必要让Equals和==表现得不一样。然而我却发现这两个方法是不完全等价的!注意,我这里讨论的是A、B都是float的情况下。那么什么情况下不一样呢?当A和B都是float.NaN的情况下,==会得出false的结论,Equals会得出是true的结论。
这下子我就懵了,为什么要这样呢?按照数学定义来说,NaN之间的比较应该是false才对,因为“非数字”之间的比较是无意义的,更不可能相等啊。也许Equals想要表达的是,他们从二进制的角度上来说是相等的——两者都是非数字。
回复: 这个算不算是Bug?7/5/2004 1:02 PM by Ninputer
Equals方法应该始终与op_Equality一致,但是对于内建类型,==的行为是语言规定的,可能与Equals不一致。
比如在VB里面的字符串比较=运算符,就可以进行不区分大小写的比较
回复: 这个算不算是Bug? 7/6/2004 9:06 AM by Junfeng Zhang
interesting. Let me ask in internal support.
回复: 这个算不算是Bug?7/6/2004 2:32 PM by Junfeng Zhang
我没有收到任何回答。不过我的理解是这样的。
Object.Equals()是判断两个object是否是同一个object。NaN是个常数,只有一个instance存在。所以NaN.Equals(NaN)应该返回true。
而NaN == NaN是数学意义上的比较,应该是false。
回复: 这个算不算是Bug? 7/7/2004 12:43 AM by qqchen
== 使用的是MSIL指令ceq,在CIL标准里面有:For floating-point number, ceq will return 0 if the numbers are unordered (either or both are NaN).
public override bool Equals(Object obj) {
if (!(obj is Single)) {
return false;
}
float temp = ((Single)obj).m_value;
if (temp == m_value) {
return true;
}
return IsNaN(temp) && IsNaN(m_value);
}
奇怪的是Equals, 居然显示的作了这个判断:
return IsNaN(temp) && IsNaN(m_value);
其实应该简单的返回temp == m_value
就行了。感觉上应该是个bug。
1楼 2004-07-05 16:19 Yu
hi,
float 是 System.Single。
看看System.Single的帮助就应该知道,想判断是不是NaN,应该使用IsNaN。
因为在帮助文件中有非常明确的说明,所以不是Bug。
用==进行判断的方法本身是程序的Bug。😃
另: 查了一下Mono的System.Single.Equals,是这样实现的。结果为真也就不奇怪了。
public override bool Equals (object o)
{
if (!(o is System.Single))
return false;
if (IsNaN ((float) o)) {
return IsNaN (m_value);
}
return ((float) o) == m_value;
}
2楼 2004-07-16 21:50 温少
==只是一个语义模型,如果没有被重载,这仅仅是:
对引用类型来说,是两个内存地址的比较
对两个值类型来说,是普通的值比较。
Java中,不允许运算符重载,虽然容易出错,不过概念倒是很清晰的。