When To Use IEquatable<T> And Why

蹲街弑〆低调 提交于 2019-11-27 09:58:30

问题


What does IEquatable<T> buy you, exactly? The only reason I can see it being useful is when creating a generic type and forcing users to implement and write a good equals method.

What am I missing?


回答1:


From the MSDN:

The IEquatable(T) interface is used by generic collection objects such as Dictionary(TKey, TValue), List(T), and LinkedList(T) when testing for equality in such methods as Contains, IndexOf, LastIndexOf, and Remove.

The IEquatable<T> implementation will require one less cast for these classes and as a result will be slightly faster than the standard object.Equals method that would be used otherwise. As an example see the different implementation of the two methods:

public bool Equals(T other) 
{
  if (other == null) 
     return false;

  return (this.Id == other.Id);
}

public override bool Equals(Object obj)
{
  if (obj == null) 
     return false;

  T tObj = obj as T;  // The extra cast
  if (tObj == null)
     return false;
  else   
     return this.Id == tObj.Id;
}



回答2:


I'm amazed that the most important reason is not mentioned here.

IEquatable<> was introduced mainly for structs for two reasons:

  1. For value types (read structs) the non-generic Equals(object) requires boxing. IEquatable<> lets a structure implement a strongly typed Equals method so that no boxing is required.

  2. For structs, the default implementation of Object.Equals(Object) (which is the overridden version in System.ValueType) performs a value equality check by using reflection to compare the values of every field in the type. When an implementer overrides the virtual Equals method in a struct, the purpose is to provide a more efficient means of performing the value equality check and optionally to base the comparison on some subset of the struct's field or properties.

Both of which improves performance.

Reference types (read classes) don't benefit as much. The IEquatable<> implementation does let you avoid a cast from System.Object but that's a very trivial gain. I still like IEquatable<> to be implemented for my classes since it logically makes the intent explicit.




回答3:


I use IEquatable<T> quite a lot, although from a pure technical perspective, it doesn't really give me any particular benefits. Overriding System.Object.Equals can provide you with the same functionality.

However, I like the explicitness of implementing IEquatable<T>. I use the concepts of Entities and Value Objects from Domain-Driven Design quite a lot, and use IEquatable<T> particularly for Value Objects, simply because it signals that a type has well-defined equality.




回答4:


Further to the other answers here's a very good reason to be implementing IEquatable<T> (and obviously overriding Equals(object) too) for value types. Just look at the default ValueType.Equals(object) code that gets called otherwise. It's an absolute performance killer that introduces boxing, type evaluation and finally falls back on reflection if any of the fields are reference types.

public override bool Equals(object obj)
{
    if (obj == null)
    {
        return false;
    }
    RuntimeType type = (RuntimeType) base.GetType();
    RuntimeType type2 = (RuntimeType) obj.GetType();
    if (type2 != type)
    {
        return false;
    }
    object a = this;
    if (CanCompareBits(this))
    {
        return FastEqualsCheck(a, obj);
    }
    FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    for (int i = 0; i < fields.Length; i++)
    {
        object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a);
        object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj);
        if (obj3 == null)
        {
            if (obj4 != null)
            {
                return false;
            }
        }
        else if (!obj3.Equals(obj4))
        {
            return false;
        }
    }
    return true;
}

In certain scenarios (such as using the value type as a key in a dictionary) it can murder performance in one foul swoop.



来源:https://stackoverflow.com/questions/2476793/when-to-use-iequatablet-and-why

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!