C#列表。转换所有效率和开销
我最近了解了List的.ConvertAll扩展名。我在今天的工作中在代码中使用了几次,将我的一个大对象列表转换为另一个对象列表。它似乎工作得很好。然而,我不确定这与仅仅迭代列表和转换对象相比有多高效或快。.ConvertAll是否使用任何特殊的方法来加快转换过程,或者只是一种不必设置循环即可转换列表的简单方法?使用ILSPy反编译:C#列表。转换所有效率和开销,c#,performance,list,convertall,C#,Performance,List,Convertall,我最近了解了List的.ConvertAll扩展名。我在今天的工作中在代码中使用了几次,将我的一个大对象列表转换为另一个对象列表。它似乎工作得很好。然而,我不确定这与仅仅迭代列表和转换对象相比有多高效或快。.ConvertAll是否使用任何特殊的方法来加快转换过程,或者只是一种不必设置循环即可转换列表的简单方法?使用ILSPy反编译: public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput>
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
if (converter == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
}
List<TOutput> list = new List<TOutput>(this._size);
for (int i = 0; i < this._size; i++)
{
list._items[i] = converter(this._items[i]);
}
list._size = this._size;
return list;
}
public List ConvertAll(转换器)
{
if(converter==null)
{
ThrowHelper.ThrowArgumentNullException(argument.converter除外);
}
列表=新列表(此大小);
对于(int i=0;i
\u项
和\u大小
成员,因此在某些情况下可能会稍微快一些
与往常一样,如果解决方案使您的工作效率更高,代码更易于阅读,等等。请使用它,直到分析揭示了不使用它的令人信服的性能理由。这是您描述它的第二种方式-基本上是一种不设置循环的简捷方式 下面是
ConvertAll()
的精髓:
List List=新列表(此大小);
对于(int index=0;index
其中,TOutput
是您要转换到的任何类型,而converter
是指示将执行转换的方法的委托
因此,它循环遍历您传入的
列表
,通过您指定的方法运行每个元素,然后返回指定类型的新列表
。对于场景中的精确计时,您需要测量自己
不要期待任何奇迹-它必须是O(n)操作,因为每个元素都需要转换并添加到目标列表中
考虑使用可枚举的
。选择,因为它将执行惰性评估,这可能会避免大列表的第二个副本,尤其是您需要在过程中对项目进行任何筛选。没有比直接到源代码更好的方法了,字面上:)
正如你所看到的,没有什么特别的魔法。它只是在列表上迭代,并通过您指定的转换器函数创建一个新项
老实说,我不知道这种方法。更惯用的.NET方法是通过使用IEnumerable
上的Select
扩展方法,比如:source.Select(input=>newsomething(input.Name))
。这有三个好处:
- 正如我所说的,它更像是一个idomatic,
ConvertAll
很可能是前C#3.0时代的残余。无论如何,这不是一个非常神秘的方法,ConvertAll
是一个非常清晰的描述,但最好还是坚持其他人知道的方法,即Select
- 它在所有
IEnumerable
上都可用,而ConvertAll
仅适用于列表的实例。无论是数组、列表还是字典,Select
都可以与它们一起使用
Select
是惰性的。在您对其进行迭代之前,它不会做任何事情。这意味着它将返回一个IEnumerable
,然后您可以通过调用ToList()
将其转换为列表,如果您实际上不需要列表,则不需要。或者,如果您只想转换和检索一百万个项目列表中的前两个项目,只需执行source.Select(input=>newsomething(input.Name))。执行(2)
但是,如果您的问题纯粹是关于将整个列表转换为另一个列表的性能,那么ConvertAll
可能会更快一些,因为它不像Select
后跟ToList
(它知道列表有一个大小,可以通过索引直接访问底层数组中的元素).谢谢您如此详尽的回答!我很好奇哪种转换方法最快,所以我在.ConvertAll、.Select和基本迭代与转换的每个转换方法周围放置了一些秒表。每个转换方法都在毫秒之内。没有显著差异。基本迭代方法最快..ConvertAll排名第二,而.Select是最慢的。很棒的帖子!但是请注意,ToList()不能延迟,因此在Select语句末尾使用.ToList()将强制直接执行整个过程。对于所有不能延迟的查询的列表,如果您需要源代码,请参阅此,也可以使用Julian链接的引用源代码:
List<TOutput> list = new List<TOutput>(this._size);
for (int index = 0; index < this._size; ++index)
list._items[index] = converter(this._items[index]);
list._size = this._size;
return list;