IEquatable与重写Object.Equals()有什么区别?

dev*_*ium 168 .net c# equality equals iequatable

我希望我的Food类能够在它等于另一个实例时进行测试Food.我稍后会对List使用它,我想使用它的List.Contains()方法.我应该实施IEquatable<Food>还是仅仅覆盖Object.Equals()?来自MSDN:

此方法通过使用默认的相等比较器来确定相等性,由对象的T的IEquatable.Equals方法的实现(列表中的值的类型)定义.

所以我的下一个问题是:.NET框架的哪些函数/类可以使用Object.Equals()?我应该首先使用它吗?

Jos*_*osh 193

主要原因是表现.当泛型介绍.NET 2.0中,他们能够增加一堆整齐班如List<T>,Dictionary<K,V>,HashSet<T>,等这些结构大量使用GetHashCodeEquals.但对于价值类型,这需要拳击.IEquatable<T>让结构实现强类型Equals方法,因此不需要装箱.因此,在使用具有泛型集合的值类型时,性能会更好.

引用类型没有那么多的好处,但IEquatable<T>实现确实可以让你避免一个强制转换,System.Object如果经常调用它会产生影响.

正如Jared Parson的博客所述,您仍然必须实现Object覆盖.

  • 这在C++中是正确的,但不是强制类型安全的.NET语言.有一个运行时转换,如果转换不成功,则抛出异常.因此,为演员付费会有很小的运行时间惩罚.编译器可以优化远程upcast例如对象o =(object)"string"; 但是向下转换 - 字符串s =(字符串)o; - 必须在运行时发生. (7认同)
  • 我建议使用Jeff Richter的C#和Jon Skeet的深度C#.至于博客,Wintellect博客很好,msdn博客等. (7认同)
  • “IEquatable&lt;T&gt;”接口除了提醒开发人员在类或结构中包含“public bool Equals(T other)”成员之外还有其他作用吗?接口的存在或不存在在运行时没有什么区别。“Equals”的重载似乎就是所需要的。 (2认同)

Cod*_*num 45

根据MSDN:

如果实现了IEquatable<T>,你也应该重写的基类的实现 Object.Equals(Object),并GetHashCode 让他们的行为与该一致的IEquatable<T>.Equals 方法.如果覆盖 Object.Equals(Object),则在调用类上的静态Equals(System.Object, System.Object)方法时也会调用重写的实现.这可确保Equals方法的所有调用都返回一致的结果.

所以似乎两者之间没有真正的功能差异,除了可以根据类的使用方式调用其中任何一个.从性能角度来看,最好使用通用版本,因为没有与之相关的装箱/拆箱惩罚.

从逻辑的角度来看,实现界面也更好.覆盖对象并不能真正告诉任何人你的类实际上是等同的.覆盖可能只是一个无用的类或浅实现.使用界面明确地说,"嘿,这个东西对于等式检查是有效的!" 这只是更好的设计.

  • 如果它们将用作Dictionary或类似集合中的键,那么结构肯定应该实现iEquatable(ofOwnType); 它将提供重大的性能提升.通过实现IEquatable(ofOwnType),非可继承类将获得轻微的性能提升.可继承的类//不应//实现IEquatable. (9认同)

thi*_*eek 27

通过一个实际的例子来扩展乔希所说的话.+1给Josh - 我的答案也是如此.

public abstract class EntityBase : IEquatable<EntityBase>
{
    public EntityBase() { }

    #region IEquatable<EntityBase> Members

    public bool Equals(EntityBase other)
    {
        //Generic implementation of equality using reflection on derived class instance.
        return true;
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as EntityBase);
    }

    #endregion
}

public class Author : EntityBase
{
    public Author() { }
}

public class Book : EntityBase
{
    public Book() { }
}
Run Code Online (Sandbox Code Playgroud)

这样,我可以重复使用Equals()方法,该方法适用于所有派生类.

  • 在"obj as EntityBase"的情况下 - 如果obj不是EntityBase类型,它将传递"null"并继续而没有任何错误或异常,但是在"(EntityBase)obj"的情况下,它将强制尝试转换obj到EntityBase,如果obj不是EntityBase类型,它将抛出InvalidCastException.是的,"as"只能应用于引用类型. (18认同)
  • 我并没有真正获得您的实现提供的额外价值.你能澄清你的抽象基类解决的问题吗? (3认同)