C#列表。转换所有效率和开销

C#列表。转换所有效率和开销,c#,performance,list,convertall,C#,Performance,List,Convertall,我最近了解了List的.ConvertAll扩展名。我在今天的工作中在代码中使用了几次,将我的一个大对象列表转换为另一个对象列表。它似乎工作得很好。然而,我不确定这与仅仅迭代列表和转换对象相比有多高效或快。.ConvertAll是否使用任何特殊的方法来加快转换过程,或者只是一种不必设置循环即可转换列表的简单方法?使用ILSPy反编译: public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput>

我最近了解了List的.ConvertAll扩展名。我在今天的工作中在代码中使用了几次,将我的一个大对象列表转换为另一个对象列表。它似乎工作得很好。然而,我不确定这与仅仅迭代列表和转换对象相比有多高效或快。.ConvertAll是否使用任何特殊的方法来加快转换过程,或者只是一种不必设置循环即可转换列表的简单方法?

使用ILSPy反编译:

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
  • 创建一个新列表
  • 通过迭代当前实例,执行指定的委托来填充新列表
  • 返回新列表
  • ConvertAll是否使用任何特殊的方法来加速转换 过程,还是仅仅是一种转换列表而不需要 必须建立一个循环

    它在转换方面没有做任何特殊的事情(它能做什么“特殊”的事情?),它直接修改私有的
    \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;