Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何克服创建列表的开销<;T>;来自IEnumerable<;T>;?_C#_.net_Linq_Performance_Ienumerable - Fatal编程技术网

C# 如何克服创建列表的开销<;T>;来自IEnumerable<;T>;?

C# 如何克服创建列表的开销<;T>;来自IEnumerable<;T>;?,c#,.net,linq,performance,ienumerable,C#,.net,Linq,Performance,Ienumerable,我正在使用一些LINQ select工具来创建一些集合,这些集合返回IEnumerable 在我的例子中,我需要一个列表,因此我将结果传递给列表的构造函数来创建一个 我想知道这样做的开销。我收藏的项目通常是几百万,所以我需要考虑这个问题。 我假设,如果IEnumerable包含ValueTypes,则性能最差 我说得对吗?那Ref类型呢?无论哪种方式,都会有调用列表的成本。添加一百万次,对吗 有办法解决这个问题吗?像我可以“重载”像LINQ选择使用扩展方法这样的方法吗?最好避免需要列表。如果您可

我正在使用一些LINQ select工具来创建一些集合,这些集合返回
IEnumerable

在我的例子中,我需要一个
列表
,因此我将结果传递给
列表
的构造函数来创建一个

我想知道这样做的开销。我收藏的项目通常是几百万,所以我需要考虑这个问题。

我假设,如果
IEnumerable
包含
ValueTypes
,则性能最差

我说得对吗?那
Ref
类型呢?无论哪种方式,都会有调用列表的成本。添加一百万次,对吗


有办法解决这个问题吗?像我可以“重载”像LINQ选择使用扩展方法这样的方法吗?

最好避免需要列表。如果您可以让来电者使用IEnumerable,您将省去一些麻烦

LINQ的ToList()将获取您的可枚举项,并使用List(IEnumerable)构造函数直接从中构造一个新列表。这与您自己创建列表的性能相同(尽管LINQ也执行空检查)


如果您自己添加元素,请使用AddRange方法而不是Add。ToList()与AddRange非常相似(因为它使用的构造函数采用IEnumerable),在这种情况下,从性能角度来看,它通常是您的最佳选择。

最好避免使用列表。如果您可以让来电者使用IEnumerable,您将省去一些麻烦

LINQ的ToList()将获取您的可枚举项,并使用List(IEnumerable)构造函数直接从中构造一个新列表。这与您自己创建列表的性能相同(尽管LINQ也执行空检查)


如果您自己添加元素,请使用AddRange方法而不是Add。ToList()与AddRange非常相似(因为它使用的构造函数采用IEnumerable),在这种情况下,从性能角度来看,这通常是最好的选择。

不要将IEnumerable传递给列表构造函数。IEnumerable有一个ToList()方法,它不可能做得比这个更糟,并且有更好的语法(IMHO)

这就是说,这只会将你的问题的答案改为“它取决于”——特别是,它取决于IEnumerable在幕后到底是什么。如果它碰巧已经是一个列表,那么ToList实际上将是免费的,当然会比另一种类型快得多。它仍然不是很快

当然,解决这个问题的最好方法是尝试找出如何在IEnumerable而不是列表上进行处理。这可能是不可能的


编辑:评论中的一些人正在争论在列表上调用ToList()是否会比if not快,以及ToList()是否会比列表构造函数快。在这一点上,投机变得毫无意义,因此这里有一些代码:

using System;
using System.Linq;
using System.Collections.Generic;

public static class ToListTest
{
    public static int Main(string[] args)
    {
        List<int> intlist = new List<int>();
        for (int i = 0; i < 1000000; i++)
            intlist.Add(i);

        IEnumerable<int> intenum = intlist;

        for (int i = 0; i < 1000; i++)
        {
            List<int> foo = intenum.ToList();
        }

        return 0;
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共静态类ToListTest
{
公共静态int Main(字符串[]args)
{
List intlist=新列表();
对于(int i=0;i<1000000;i++)
添加(i);
IEnumerable intenum=intlist;
对于(int i=0;i<1000;i++)
{
List foo=intenum.ToList();
}
返回0;
}
}
使用IEnumerable(实际上是一个列表)运行这段代码比使用LinkedList或Stack(在我的pokey 2.4 GHz P4上,使用Mono 1.2.6)替换它要快6-10倍。可以想象,这可能是由于ToList()和LinkedList或Stack枚举的特定实现之间的一些不幸交互,但至少还有一点:速度将取决于IEnumerable的底层类型。也就是说,即使有一个列表作为源,我仍然需要6秒钟来进行1000个ToList()调用,所以这远不是免费的

下一个问题是ToList()是否比List构造函数更智能。答案是否定的:列表构造函数与ToList()一样快。事后看来,Jon Skeet的推理是有道理的——我只是忘记了ToList()是一种扩展方法。在语法上,我仍然(非常)喜欢ToList(),但没有性能上的理由使用它


因此,简而言之,最好的答案仍然是“如果可以避免,就不要转换为列表”。除此之外,实际性能将在很大程度上取决于IEnumerable实际上是什么,但充其量它将是缓慢的,而不是缓慢的。为了反映这一点,我修改了我的原始答案。

不要将IEnumerable传递给列表构造函数。IEnumerable有一个ToList()方法,它不可能做得比这个更糟,并且有更好的语法(IMHO)

这就是说,这只会将你的问题的答案改为“它取决于”——特别是,它取决于IEnumerable在幕后到底是什么。如果它碰巧已经是一个列表,那么ToList实际上将是免费的,当然会比另一种类型快得多。它仍然不是很快

当然,解决这个问题的最好方法是尝试找出如何在IEnumerable而不是列表上进行处理。这可能是不可能的


编辑:评论中的一些人正在争论在列表上调用ToList()是否会比if not快,以及ToList()是否会比列表构造函数快。在这一点上,投机变得毫无意义,因此这里有一些代码:

using System;
using System.Linq;
using System.Collections.Generic;

public static class ToListTest
{
    public static int Main(string[] args)
    {
        List<int> intlist = new List<int>();
        for (int i = 0; i < 1000000; i++)
            intlist.Add(i);

        IEnumerable<int> intenum = intlist;

        for (int i = 0; i < 1000; i++)
        {
            List<int> foo = intenum.ToList();
        }

        return 0;
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共静态类ToListTest
{
公共静态int Main(字符串[]args)
{
List intlist=新列表();
对于(int i=0;i<1000000;i++)
添加(i);
IEnumerable intenum=intlist;
法罗群岛
Foo[] foo = new Foo[100];
IEnumerable<string> query = foo.Select(x => x.Name);
List<string> queryList = new List<string>(foo.Length);
queryList.AddRange(query);
var result = from item in collection
             where item.Id > 10 //or some more sensible condition
             select Operation(item);
var result = from filteredItem in (from item in collection
                                  where item.Id > 10 //or some more sensible condition
                                  select Operation(item))
                 where filteredItem.SomePropertyAvailableAfterFirstTransformation == "new"
                 select SecondTransfomation(filteredItem);