List.Contains()的MSDN描述说


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


并且List.IndexOf()的描述说


  此方法使用默认的相等比较器EqualityComparer.Default来确定相等。T为列表中值的类型。


EqualityComparer.Default描述说


  Default属性检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它返回一个EqualityComparer,它使用T提供的Object.Equals和Object.GetHashCode的替代。


这有点可疑-Contains的描述仅提及IEquatable,并且可能将未实现IEquatable的内容放入List

所以我猜他们只是使用相同的语义,也许Contains()重用了IndexOf()

那么它们在比较方面是否完全等效?

最佳答案

简短答案:


否,Contains()不重用IndexOf()
是的,它们在比较方面相当


我对(ReSharper)进行了反编译,发现最终两者都使用了抽象的EqualityComparer<T>.Default.Equals(T x, T y)方法。 DefaultEqualityComparer<T>实例根据类型T初始化(并缓存)。

清单包含

EqualityComparer<T> @default = EqualityComparer<T>.Default;
// for loop
if (@default.Equals(this._items[index], item))
    return true;


List.IndexOf

return Array.IndexOf<T>(this._items, item, 0, this._size);


Array.IndexOf

public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
    // Some assertions
    return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
}


EqualityComparer.IndexOf

internal virtual int IndexOf(T[] array, T value, int startIndex, int count)
{
    // for loop
    if (this.Equals(array[index], value))
        return index;
}


这就是实例化EqualityComparer.Default的方式

public static EqualityComparer<T> Default
{
  get
  {
    EqualityComparer<T> equalityComparer = EqualityComparer<T>.defaultComparer;
    if (equalityComparer == null)
    {
      equalityComparer = EqualityComparer<T>.CreateComparer();
      EqualityComparer<T>.defaultComparer = equalityComparer;
    }
    return equalityComparer;
  }
}

private static EqualityComparer<T> CreateComparer()
{
  RuntimeType genericParameter1 = (RuntimeType) typeof (T);

  if ((Type) genericParameter1 == typeof (byte))
    return (EqualityComparer<T>) new ByteEqualityComparer();
  // Some ifs go on
  else
    return (EqualityComparer<T>) new ObjectEqualityComparer<T>();
}

09-25 19:29