List.Contains是否与List.IndexOf等效完全比较?

时间:2014-04-17 12:44:00

标签: c# .net list generics

List.Contains()的MSDN说明

  

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

以及List.IndexOf()的说明

  

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

EqualityComparer.Default说明

  

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

哪种情况有点可疑 - Contains的说明只提及IEquatable,并且可以将未实现IEquatable的内容放入List

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

他们完全等同于比较吗?

2 个答案:

答案 0 :(得分:2)

简短回答:

  • 不,Contains()不会重复使用IndexOf()
  • 是的,它们相当于比较

我反编译(ReSharper)并看到最终都使用抽象EqualityComparer<T>.Default.Equals(T x, T y)方法。根据类型T初始化(和缓存)Default的{​​{1}}实例。

<强> List.Contains

EqualityComparer<T>

<强> List.IndexOf

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

<强> Array.IndexOf

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

<强> EqualityComparer.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.Default 的实例化方式

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

答案 1 :(得分:1)

  

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

不,它没有。

List.Contains实现为:

来自Reference Source .NET Framework 4.5.1 - Microsoft

public bool Contains(T item) {
    if ((Object) item == null) {
        for(int i=0; i<_size; i++)
            if ((Object) _items[i] == null)
                return true;
        return false;
    }
    else {
        EqualityComparer<T> c = EqualityComparer<T>.Default;
        for(int i=0; i<_size; i++) {
            if (c.Equals(_items[i], item)) return true;
        }
        return false;
    }
}

List<T>.IndexOf使用Array.IndexOf

的位置

Source: List<T>.IndexOf

public int IndexOf(T item)
{
    Contract.Ensures(Contract.Result<int>() >= -1);
    Contract.Ensures(Contract.Result<int>() < Count);
    return Array.IndexOf(_items, item, 0, _size);
}

Array.IndexOf is implemented

public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
    if (array == null)
    {
        throw new ArgumentNullException("array");
    }

    if (startIndex < 0 || startIndex > array.Length)
    {
        throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
    }

    if (count < 0 || count > array.Length - startIndex)
    {
        throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
    }
    Contract.Ensures(Contract.Result<int>() < array.Length);
    Contract.EndContractBlock();

    return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);

}