对于CLR类型,Object.Equals(objA,objB),objA.Equals(objB)和objA == objB之间的区别?

时间:2011-11-08 15:21:59

标签: c# .net iequatable equals-operator object-equality

我想知道CLR类型是否会返回以下不同的结果:

Object.Equals(objA, objB)

objA.Equals(objB)

(objA == objB)

我确实意识到在CLR之外有人可以轻松实现IEqualtable Equals并且不正确地重载==运算符。我并不关心那些不正确实施这些的人。我所理解的是类(包括String,Int32等)以不同的方式实现这些。

此外,如果可能的话,哪一个应该是用于整体比较的(全面的)。我不知道这是因为我遇到了一个文件,它在整个视图模型中使用Object.Equals(objA, objB)而不是其他两个文件。

private string _name;
public string Name
{
    get { return _name; }
    set
    {
        if (Equals(_name, value)) return;
        ...
    }
}

private int _id;
public int Id
{
    get { return _id; }
    set
    {
        if (Equals(_id, value)) return;
        ...
    }
}

private Object _obj;
public Object TheObject
{
    get { return _obj; }
    set
    {
        if (Equals(_obj, value)) return;
        ...
    }
}

2 个答案:

答案 0 :(得分:6)

Object.Equals(a,b)为null安全。它可以回答,例如等于(null,null),这是真的。除此之外,它只调用常规的Equals()方法。据我所知,clr字符串和基本类型具有定义的相等运算符,其工作方式与Object.Equals(a,b)完全相同。

对于非null objA和objB,Object.Equals(objA,objB),objA.Equals(objB)和objB.Equals(objA)如果正确实现了Equals方法,则应该是等效的。

在您发布的代码中,使用Equals(_obj,value)似乎是正确的。

如果你想要完整的相等比较列表,不要忘记objA.ReferenceEquals(objB),它是一种在许多情况下都很有用的相等。

答案 1 :(得分:1)

对于任何浮点数Equals==表现不同。

    遵循IEEE逻辑
  • NaN==NaN => false
  • NaN.Equals(NaN) => true要求任何事情必须与自己相等。

当然Equals被覆盖,即使静态类型是基类型也可以工作,而==是重载的,只有在静态类型被重载时才有效。

我几乎从未直接致电x.Equals(y)。例如,它不处理x null,它的不对称是丑陋的IMO。静态object.Equals(x,y)调用虚拟object.Equals(y)方法,但添加了空值处理。

IEquatable<T>.Equals(other)在所有表现良好的类型上等同于object.Equals(other),但它避免了在值类型中装箱。

总之,当静态类型已知时,我通常更喜欢==,而对于泛型类型,或者如果静态类型与运行时类型不匹配,我通常更喜欢EqualityComparer<T>.Default


在您的示例中NameId==Equals的行为方式相同,因为stringint已被密封。< / p> 另一方面,

TheObject针对某些类型展示了==Equals的不同行为。例如,如果您使用string,那么Equals将使用值相等,而==将使用引用相等。