代码之家  ›  专栏  ›  技术社区  ›  Jack Kada

何时使用iequatable以及为什么

c#
  •  35
  • Jack Kada  · 技术社区  · 15 年前

    我只是不明白-你到底买了什么?是吗?

    我能看到它有用的唯一原因是当创建一个泛型类型并强制用户实现和编写一个好的equals方法时。

    我错过了什么

    4 回复  |  直到 7 年前
        1
  •  35
  •   shA.t Rami Jamleh    7 年前

    MSDN :

    这个 IEquatable(T) 接口由泛型集合对象使用,例如 Dictionary(TKey, TValue) , List(T) ,和 LinkedList(T) 当在以下方法中测试相等性时: Contains , IndexOf , LastIndexOf ,和 Remove .

    这个 IEquatable<T> 对于这些类,实现需要较少的强制转换,因此比标准稍快一点。 object.Equals 否则将使用的方法。例如,可以看到两种方法的不同实现:

    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
  •  29
  •   nawfal Donny V.    11 年前

    我很惊讶,最重要的原因没有在这里提到。

    IEquatable<> 主要针对结构介绍,原因有两个:

    1. 对于值类型(读取结构),非泛型 Equals(object) 需要拳击。 IEquatable<gt; 允许结构实现强类型 Equals 方法,以便不需要装箱。

    2. 对于结构,默认实现 Object.Equals(Object) (中的重写版本) System.ValueType )通过使用反射来比较类型中每个字段的值,执行值相等性检查。当实现者重写结构中的虚equals方法时,目的是提供一种更有效的方法来执行值相等性检查,并可选地基于结构字段或属性的某些子集进行比较。

    这两者都提高了性能。

    引用类型(读取类)的好处不大。这个 IEquatable<gt; 实现允许您避免 System.Object 但这是一个微不足道的收获。我还是喜欢 IEquatable<gt; 为我的类实现,因为它在逻辑上使意图显式。

        3
  •  11
  •   Mark Seemann    15 年前

    我用 IEquatable<T> 相当多,虽然从纯粹的技术角度来看,它并没有给我任何特别的好处。压倒一切 System.Object.Equals 可以为您提供相同的功能。

    但是,我喜欢 明确性 实施的 IEquatable<T> . 我使用的概念是 实体 价值客体 Domain-Driven Design 相当多,而且使用 IEquatable<T> 尤其是对于值对象,因为它表示类型具有定义良好的相等性。

        4
  •  2
  •   0b101010    10 年前

    除其他答案外,这里还有一个很好的理由要实施 IEquatable<T> (显然是压倒性的 Equals(object) 也适用于值类型。看看默认值 ValueType.Equals(object) 以其他方式调用的代码。它是一个绝对的性能杀手,它引入了装箱、类型评估,如果任何字段都是引用类型,那么它最终都会反射回来。

    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;
    }
    

    在某些情况下(如将值类型用作字典中的键),它会一下子破坏性能。