简体   繁体   English

IEquatable 和只是覆盖 Object.Equals() 有什么区别?

[英]What's the difference between IEquatable and just overriding Object.Equals()?

I want my Food class to be able to test whenever it is equal to another instance of Food .我希望我的Food类能够在它等于Food另一个实例时进行测试。 I will later use it against a List, and I want to use its List.Contains() method.稍后我将针对 List 使用它,并且我想使用它的List.Contains()方法。 Should I implement IEquatable<Food> or just override Object.Equals() ?我应该实现IEquatable<Food>还是只覆盖Object.Equals() From MSDN:来自 MSDN:

This method determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable.Equals method for T (the type of values in the list).此方法通过使用默认相等比较器来确定相等性,正如对象对 T(列表中值的类型)的 IEquatable.Equals 方法的实现所定义的那样。

So my next question is: which functions/classes of the .NET framework make use of Object.Equals() ?所以我的下一个问题是:.NET 框架的哪些函数/类使用Object.Equals() Should I use it in the first place?我应该首先使用它吗?

The main reason is performance.主要原因是性能。 When generics were introduced in .NET 2.0 they were able to add a bunch of neat classes such as List<T> , Dictionary<K,V> , HashSet<T> , etc. These structures make heavy use of GetHashCode and Equals .在 .NET 2.0 中引入泛型时,它们能够添加一堆整洁的类,例如List<T>Dictionary<K,V>HashSet<T>等。这些结构大量使用GetHashCodeEquals But for value types this required boxing.但是对于值类型,这需要装箱。 IEquatable<T> lets a structure implement a strongly typed Equals method so no boxing is required. IEquatable<T>允许结构实现强类型的Equals方法,因此不需要装箱。 Thus much better performance when using value types with generic collections.因此,在将值类型与泛型集合一起使用时性能要好得多。

Reference types don't benefit as much but the IEquatable<T> implementation does let you avoid a cast from System.Object which can make a difference if it's called frequently.引用类型没有那么多好处,但IEquatable<T>实现确实让您避免了System.ObjectIEquatable<T> ,如果它被频繁调用,这可能会产生影响。

As noted on Jared Parson's blog though, you must still implement the standard Object.Equals and Object.GetHashcode overrides.不过,正如Jared Parson 的博客所述,您仍然必须实现标准的Object.EqualsObject.GetHashcode覆盖。

According to the MSDN :根据MSDN

If you implement IEquatable<T> , you should also override the base class implementations of Object.Equals(Object) and GetHashCode so that their behavior is consistent with that of the IEquatable<T>.Equals method.如果您实现IEquatable<T> ,您还应该覆盖Object.Equals(Object)GetHashCode的基类实现,以便它们的行为与IEquatable<T>.Equals方法的行为一致。 If you do override Object.Equals(Object) , your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class.如果您确实覆盖Object.Equals(Object) ,则您的覆盖实现也会在对类上的静态Equals(System.Object, System.Object)方法的调用中调用。 This ensures that all invocations of the Equals method return consistent results.这可确保Equals方法的所有调用返回一致的结果。

So it seems that there's no real functional difference between the two except that either could be called depending on how the class is used.因此,这两者之间似乎没有真正的功能差异,只是可以根据类的使用方式调用两者。 From a performance standpoint, it's better to use the generic version because there's no boxing/unboxing penalty associated with it.从性能的角度来看,最好使用通用版本,因为没有与之相关的装箱/拆箱惩罚。

From a logical standpoint, it's also better to implement the interface.从逻辑的角度来看,实现接口也更好。 Overriding the object doesn't really tell anyone that your class is actually equatable.覆盖该对象并没有真正告诉任何人你的类实际上是等价的。 The override may just be a do nothing class or a shallow implementation.覆盖可能只是一个什么都不做的类或一个浅层的实现。 Using the interface explicitly says, "Hey, this thing is valid for equality checking!"使用接口明确地说,“嘿,这东西对等式检查有效!” It's just better design.这只是更好的设计。

Extending what Josh said with a practical example.用一个实际的例子来扩展乔希所说的。 +1 to Josh - I was about to write the same in my answer. +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() { }
}

This way, I have re-usable Equals() method that works out of the box for all my derived classes.这样,我就有了可重用的 Equals() 方法,该方法对我的所有派生类都是开箱即用的。

If we call object.Equals , it forces to expensive boxing on value types.如果我们调用object.Equals ,它会强制对值类型进行昂贵的装箱。 This is undesirable in performance-sensitive scenarios.这在性能敏感的场景中是不可取的。 The solution is to use IEquatable<T> .解决方案是使用IEquatable<T>

public interface IEquatable<T>
{
  bool Equals (T other);
}

The idea behind IEquatable<T> is that it gives the same result as object.Equals but more quickly.背后的想法IEquatable<T>的是,它提供了相同的结果object.Equals但更迅速。 The constrain where T : IEquatable<T> must be used with generic types like below.约束where T : IEquatable<T>必须与下面的泛型类型一起使用。

public class Test<T> where T : IEquatable<T>
{
  public bool IsEqual (T a, T b)
  {
    return a.Equals (b); // No boxing with generic T
  }
}

otherwise, it binds to slower object.Equals() .否则,它绑定到slower object.Equals()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 重写Object.Equals并实现IEquatable &lt;&gt;时无法访问的代码? - Unreachable code when overriding Object.Equals and implementing IEquatable<>? obj1.Equals(obj2)和c#中的静态Object.Equals(obj1,obj2)有什么区别? - What's the difference between obj1.Equals(obj2) and static Object.Equals(obj1, obj2) in c#? Assert.AreEquals调用object.Equals而不管IEquatable实现如何 - Assert.AreEquals calls object.Equals irrespective of IEquatable implemenations 什么是Object.Equals(obj,null)和obj == null之间的区别 - Whats the Difference between Object.Equals(obj, null) and obj == null IComparable 和 IEquatable 接口之间有什么区别? - What's the difference between IComparable & IEquatable interfaces? 重写Object.Equals时,是否适合使用传入的对象的Equals(MyType)? - When overriding Object.Equals, is it appropriate to use the passed in object's Equals(MyType)? 对于CLR类型,Object.Equals(objA,objB),objA.Equals(objB)和objA == objB之间的区别? - Difference between Object.Equals(objA, objB), objA.Equals(objB) and objA == objB for CLR types? c#中Object.Equals(object,object)和Object.ReferenceEquals(object,object)之间的区别 - difference between Object.Equals(object,object) and Object.ReferenceEquals(object,object) in c# IEquatable上的重载等于 - Overriding Equals on IEquatable IEquatable之间的差异 <T> ,IEqualityComparer <T> ,并在自定义对象集合上使用LINQ时覆盖.Equals()? - Differences between IEquatable<T>, IEqualityComparer<T>, and overriding .Equals() when using LINQ on a custom object collection?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM