C# 一个非常基本的自动扩展列表/数组

C# 一个非常基本的自动扩展列表/数组,c#,performance,data-structures,stack,memory-management,C#,Performance,Data Structures,Stack,Memory Management,我有一个方法,它返回一个固定类型对象的数组(比如说MyObject) 该方法创建一个新的空堆栈。然后,它做一些工作并将一些MyObjects推送到堆栈的末尾。最后,它返回Stack.ToArray() 它不会更改已添加的项或其属性,也不会删除它们。要添加的元素数量将影响性能。不需要对元素进行排序/排序 堆栈是最好的使用方法吗?或者我必须切换到集合或列表,以确保更好的性能和/或更低的内存成本?堆栈不会比列表更快 为了获得最佳性能,您应该使用列表,并将容量设置为大于或等于您计划添加的项目数 也许可以

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

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

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

堆栈是最好的使用方法吗?或者我必须切换到
集合
列表
,以确保更好的性能和/或更低的内存成本?

堆栈
不会比
列表
更快


为了获得最佳性能,您应该使用
列表
,并将
容量
设置为大于或等于您计划添加的项目数

也许可以使用LinkedList


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

如果顺序无关紧要,并且您的方法不需要添加/删除/编辑已处理的项目,那么为什么不返回并只返回每个项目呢

然后,您的调用代码可以直接使用序列,也可以根据需要调用等

例如

// 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;
     }
}
//直接使用序列
foreach(GetObjects()中的MyObject项)
{
Console.WriteLine(item.ToString());
}
// ...
//转换为数组
MyObject[]myArray=GetObjects().ToArray();
// ...
//转换为列表
List myList=GetObjects().ToList();
// ...
公共IEnumerable GetObjects()
{
foreach(GetObjectsFromSomewhere()中的MyObject foo)
{
MyObject bar=DoSomeProcessing(foo);
屈服回程杆;
}
}

Stack
在本例中并不比
List
快,因此我可能会使用
List
,除非您所做的事情与“Stack”类似<当您想要的基本上是一个可扩展的数组时,代码>列表是更标准的数据结构,而当您需要集合的行为时,通常使用堆栈。

如果您需要堆栈()的语义,那么答案无疑是,是的,堆栈是您的最佳解决方案。如果您从一开始就知道最终将包含多少元素,那么可以通过调用

如果您担心将堆栈复制到数组中的内存开销,并且只需要顺序访问结果,那么您可以将
堆栈
作为
IEnumerable
返回,而不是数组,并使用
foreach
对其进行迭代


综上所述,除非这段代码证明它在性能方面存在问题(即,通过查看探查器中的数据),否则我不会花太多时间来使用语义调用。

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

但是,当超过初始容量时,堆栈和列表都会自动增加其内部项目数组。这涉及到创建一个新的较大数组并复制所有项。这需要一些性能

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

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

var stack = new Stack<T>(200);  // Initial capacity of 200 items.
var stack=新堆栈(200);//初始容量为200件。
如果要做的只是追加,则不需要堆栈。您可以使用List.Add()和ToArray


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

除非他需要返回数组或
IList
。即使如此,它们也可能不太好。这完全取决于情况(大多数情况下,链表都会丢失)。对于链表,您的内存开销是线性的(“下一个”指针),而不是常量,在指向时,您只能进行顺序访问,而且它们的缓存性能非常糟糕。其主要优点是,您不必承担调整大小的成本,也不必“浪费”空白空间。请您描述一下
列表在填充或接近填充时是如何扩展的,以及在不指定长度时,它的初始大小是多少。@Subby: