【问题标题】:A very basic auto-expanding list/array一个非常基本的自动扩展列表/数组
【发布时间】:2011-01-31 18:36:16
【问题描述】:

我有一个返回固定类型对象数组的方法(比如说MyObject)。

该方法创建一个新的空Stack<MyObject>。然后,它会做一些工作并将一些MyObjects 推到Stack 的末尾。最后,它返回Stack.ToArray()

它不会更改已添加的项目或其属性,也不会删除它们。要添加的元素数量会降低性能。无需对元素进行排序/排序。

Stack 是不是最好用?或者我必须切换到CollectionList 以确保更好的性能和/或更低的内存成本?

【问题讨论】:

    标签: c# performance data-structures stack memory-management


    【解决方案1】:

    Stack<T> 不会比List<T> 快。

    为获得最佳性能,您应该使用List<T> 并将Capacity 设置为大于或等于您计划添加的项目数的数字。

    【讨论】:

    【解决方案2】:

    如果顺序无关紧要,并且您的方法不需要添加/删除/编辑已处理的项目,那么为什么不随手返回 IEnumerable<MyObject>yield 每个项目?

    那么你的调用代码既可以直接使用IEnumerable<MyObject>序列,也可以根据需要调用ToArrayToList等。

    例如...

    // use the sequence directly
    foreach (MyObject item in GetObjects())
    {
        Console.WriteLine(item.ToString());
    }
    
    // ...
    
    // convert to an array
    MyObject[] myArray = GetObjects().ToArray();
    
    // ...
    
    // convert to a list
    List<MyObject> myList = GetObjects().ToList();
    
    // ...
    
    public IEnumerable<MyObject> GetObjects()
    {
         foreach (MyObject foo in GetObjectsFromSomewhereElse())
         {
             MyObject bar = DoSomeProcessing(foo);
             yield return bar;
         }
    }
    

    【讨论】:

    • 除非他需要返回一个数组或IList
    【解决方案3】:

    Stack&lt;T&gt; 在这种情况下并不比List&lt;T&gt; 快,所以我可能会使用List,除非你正在做的事情是“类似堆栈的”。 List&lt;T&gt; 是更标准的数据结构,当您想要的基本上是一个可增长的数组时使用,而堆栈通常在您需要集合的 LIFO 行为时使用。

    【讨论】:

      【解决方案4】:

      为此,框架中没有任何其他集合的性能比 Stack 好得多。

      但是,当超出初始容量时,Stack 和 List 都会自动增长它们的内部项目数组。这涉及创建一个新的更大的数组并复制所有项目。这会消耗一些性能。

      如果您事先知道项目的数量,请将您的集合初始化为该容量以避免自动增长。如果不清楚,请选择一个不太可能不足的容量。

      大多数内置集合都将初始容量作为构造函数参数:

      var stack = new Stack<T>(200);  // Initial capacity of 200 items.
      

      【讨论】:

        【解决方案5】:

        也许使用 LinkedList?

        虽然 LinkedLists 只对顺序数据有用。

        【讨论】:

        • 即便如此,它们也可能不太好。这完全取决于情况(大多数情况下,链表会丢失)。使用链表,您有线性内存开销(“下一个”指针)而不是常量,您只能按顺序访问,而且它们的缓存性能很差。主要优点是您无需承担调整大小的成本,也不会“浪费”空白空间。
        【解决方案6】:

        如果您要做的只是追加,则不需要 Stack。您可以使用 List.Add (http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx),然后使用 ToArray。

        (您还需要设置初始容量,正如其他人指出的那样。)

        【讨论】:

          【解决方案7】:

          如果您需要堆栈的语义 (last-in first-out),那么答案是,毫无疑问,是的,堆栈是您的最佳解决方案。如果您从一开始就知道最终会包含多少个元素,则可以通过调用 constructor that receives a capacity 来避免自动调整大小的成本。

          如果您担心将堆栈复制到数组中的内存成本,并且您只需要顺序访问结果,那么,您可以将Stack&lt;T&gt; 作为@987654324 返回@ 而不是数组,并使用 foreach 对其进行迭代。

          说了这么多,除非这段代码证明它在性能方面存在问题(即,通过查看分析器中的数据),否则我不会费心去做语义调用。

          【讨论】:

            猜你喜欢
            • 2013-02-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多