通过StackOverflow中的旅行,ToList()
(或ICollection
派生的类的ICollection<T>
扩展方法有很多用法。
我已经退出了好的'反编译器,看看ToList()
扩展方法是如何执行的,并且它可以随时枚举该集合。通过源头我遇到了:
[__DynamicallyInvokable]
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
现在这很简单,因此ToList()
扩展方法只是使用源对象创建一个新的List<T>
。深入挖掘List构造函数会显示此行。
ICollection<T> ts = collection as ICollection<T>;
//.. ommited code
ts.CopyTo(this._items, 0);
如您所愿,您将深入研究CopyTo
方法。这是我被卡住的地方。在完成所有挖掘方法调用之后,我们将进入最后的extern
方法调用
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
[SecurityCritical]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
我的问题是(虽然我似乎无法找到它)ToList()
扩展方法(ICollection<T>.CopyTo()
)在执行时是否迭代了Collection(Array)的所有对象?
子问题:我在哪里可以找到上面extern void Copy()
的来源?
编辑:我已经直接编辑了这个问题,因为我意识到之后我正在尝试获取接口的规范而不是实现。遗憾
答案 0 :(得分:12)
我的问题是(虽然我似乎无法找到它)
ToList()
扩展方法(ICollection<T>.CopyTo())
遍历所有 集合中的对象(Array
)何时执行?
不,它没有。它只是使用Array.Copy
复制基础数组存储。
的更新强> 的
只是为了确保我的答案得到正确解释。 ToList()
在直接在另一个List<T>
或T[]
数组(或其他实现ICollection.CopyTo
而没有枚举数的集合中调用时,不会枚举源集合)。
当您致电ToList<>
时在Enumerable.Range(0, 1000).ToList()
上会有一个枚举。使用任何LINQ方法时也会执行枚举,例如: myList.Select(x => x.PropertyName).ToList()
将导致枚举。
更新结束
void ICollection.CopyTo(Array array, int arrayIndex)
{
if (array != null && array.Rank != 1)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
try
{
Array.Copy(this._items, 0, array, arrayIndex, this._size);
}
catch (ArrayTypeMismatchException)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
}
}
使用非托管c ++代码以高效的方式执行此操作:
此方法等同于标准C / C ++函数
memmove
,而不是memcpy.
答案 1 :(得分:1)
ToList()扩展方法(ICollection.CopyTo())是否遍历Collection的所有对象
这取决于特定类中ICollection<T>
的实现方式。
例如,List<T>
实现只复制数组(不进行迭代),因为内部List<T>
使用数组作为存储。但没有什么可以阻止你(或其他人)编写实现,它将迭代源集合。
由我在哪里可以找到extern void Copy()上面的源代码
MethodImpl(MethodImplOptions.InternalCall)
标记的方法在非托管C ++代码中实现。我不确定,他们有任何开源。但我想,最终,有一些像memcpy(...)
。
答案 2 :(得分:0)
extern 表示该函数将在C#代码之外实现。它可以用C / C ++实现。更多细节: