为List <T>()提供大小参数

tra*_*m_3 1 c# performance list

List<T>()in 的默认容量System.Collections.Generic为0.

说我有一个功能

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e)
{
    var list = new List<SomeType>();
    foreach (var elem in e)
    {
        list.Add(new SomeType
        {
            SomeProperty = elem.OtherProperty
        });
    }
    return list;
}
Run Code Online (Sandbox Code Playgroud)

list在运行循环之前设置了大小,如下所示:

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e)
{
    var list = new List<SomeType>(e.Count());
    foreach (var elem in e)
    {
        list.Add(new SomeType
        {
            SomeProperty = elem.OtherProperty
        });
    }
    return list;
}
Run Code Online (Sandbox Code Playgroud)

它是否会影响运行时间,或者没有理由这样做,因为它的大小e是"动态的"?

xan*_*tos 5

这取决于IEnumerable<OtherType> e...... 的类型

e.Count()
Run Code Online (Sandbox Code Playgroud)

可以枚举ejust来计算它...如果e是对db的查询,它将被执行两次,一次用于e.Count()和一次用于foreach......慢!

如果e是一个List<>或一个OtherType[]或其他类型的实现ICollection<>然后Count()使用该Count属性,所以它不枚举IEnumerable<>.

请注意,对于这个简单的情况,您可以:

return e.Select(x => new SomeType { SomeProperty = x.OtherProperty })
        .ToList();
Run Code Online (Sandbox Code Playgroud)

现在......正如@Jonathan注意到的那样,你回来了IEnumerable<>,所以你可以:

return e.Select(x => new SomeType { SomeProperty = x.OtherProperty });
Run Code Online (Sandbox Code Playgroud)

并且幸福快乐......或者你可以

private IEnumerable<SomeType> DoStuff(IEnumerable<OtherType> e)
{
    foreach (var elem in e)
    {
        yield return new SomeType
        {
            SomeProperty = elem.OtherProperty
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

(这几乎等同于做Select,但如果你有一个复杂的表达式来转换元素,也许使用Select变得很麻烦)

或者,如果您真的想要创建List<>并在可能的情况下进行预设:

ICollection<T> c = e as ICollection<T>;
int count = c != null ? c.Count : 0;

var list = new List<SomeType>(count);
Run Code Online (Sandbox Code Playgroud)

一如既往,请记住,除非你真的确定,否则你不应该IEnumerable<>多次枚举

  1. 它实际上是List<>伪装的一个或其他集合,因此数据已经存在,并且多次枚举它没有问题

要么

  1. 您知道每次IEnumerable<>枚举它都将从头开始重建,但成本可以忽略不计.