Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# List.Contains是否完全与List.IndexOf等效?_C#_.net_List_Generics - Fatal编程技术网

C# List.Contains是否完全与List.IndexOf等效?

C# List.Contains是否完全与List.IndexOf等效?,c#,.net,list,generics,C#,.net,List,Generics,MSDN对says的描述 此方法通过使用默认的相等比较器来确定相等,该比较器由对象对T(列表中的值类型)的IEquatable.Equals方法的实现定义 以及对其的描述 此方法使用默认的相等比较器EqualityComparer确定相等。默认值为T,列表中的值类型 描述说 默认属性检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它将返回一个EqualityComparer,使用T提供的Object.Equals和Obj

MSDN对says的描述

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

以及对其的描述

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

描述说

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

这有点可疑-对
的描述包含
只提到
IEquatable
,并且有可能将未实现
IEquatable
的内容放入
列表中

所以我猜它们只是使用相同的语义,可能
Contains()
重用
IndexOf()

那么,它们是否完全等同于比较呢?

简单回答:

  • 否,
    Contains()
    不重用
    IndexOf()
  • 是的,它们在比较方面是等价的
我反编译(ReSharper)并看到最终两者都使用抽象
EqualityComparer.Default.Equals(tx,tyy)
方法。
EqualityComparer
Default
实例根据类型T进行初始化(并缓存)

列表。包含

EqualityComparer<T> @default = EqualityComparer<T>.Default;
// for loop
if (@default.Equals(this._items[index], item))
    return true;
这就是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>();
}
publicstaticequalitycomparer默认值
{
得到
{
EqualityComparer EqualityComparer=EqualityComparer.defaultComparer;
如果(equalityComparer==null)
{
equalityComparer=equalityComparer.CreateComparer();
EqualityComparer.defaultComparer=EqualityComparer;
}
返回均衡器;
}
}
专用静态EqualityComparer CreateComarer()
{
RuntimeType genericParameter1=(RuntimeType)typeof(T);
if((Type)genericParameter1==typeof(byte))
return(EqualityComparer)new ByteEqualityComparer();
//有些假设还在继续
其他的
返回(EqualityComparer)新对象EqualityComparer();
}
所以我猜它们只是使用相同的语义,可能包含() 重用IndexOf()

不,没有

List.Contains实现为:

作为

公共静态int IndexOf(T[]数组,T值,int startIndex,int计数)
{
if(数组==null)
{
抛出新的ArgumentNullException(“数组”);
}
if(startIndex<0 | | startIndex>array.Length)
{
抛出新ArgumentOutOfRangeException(“startIndex”,Environment.GetResourceString(“ArgumentOutOfRange_索引”);
}
if(count<0 | | count>array.Length-startIndex)
{
抛出新ArgumentOutOfRangeException(“count”,Environment.GetResourceString(“ArgumentOutOfRange\u count”);
}
Contract.Contract(Contract.Result()
public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
    // Some assertions
    return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
}
internal virtual int IndexOf(T[] array, T value, int startIndex, int count)
{
    // for loop
    if (this.Equals(array[index], value))
        return index;
}
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>();
}
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;
    }
}
public int IndexOf(T item)
{
    Contract.Ensures(Contract.Result<int>() >= -1);
    Contract.Ensures(Contract.Result<int>() < Count);
    return Array.IndexOf(_items, item, 0, _size);
}
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);

}