C# List.Contains是否完全与List.IndexOf等效?
MSDN对says的描述 此方法通过使用默认的相等比较器来确定相等,该比较器由对象对T(列表中的值类型)的IEquatable.Equals方法的实现定义 以及对其的描述 此方法使用默认的相等比较器EqualityComparer确定相等。默认值为T,列表中的值类型 描述说 默认属性检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它将返回一个EqualityComparer,使用T提供的Object.Equals和Object.GetHashCode的重写 这有点可疑-对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
的描述包含只提到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);
}