如何克隆 Stack
我的代码中有几个堆栈用于跟踪我的逻辑位置。在某些时候,我需要复制堆栈,但我似乎无法以保留顺序的方式克隆它们。我只需要浅层复制(引用,而不是对象)。
正确的方法是什么?或者我应该使用其他类型的堆栈?
I have few stacks in my code that I use to keep track of my logical location. At certain times I need to duplicate the stacks, but I can't seem to clone them in such way that it preserves the order. I only need shallow duplication (references, not object).
What would be the proper way to do it? Or should I use some other sort of stacks?
I saw this post Stack Clone Problem: .NET Bug or Expected Behaviour?, but not sure how to setup clone method for the Stack<T>
class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以将其编写为扩展方法,因为
这是必要的,因为我们在这里使用的实现,它将重复地从堆栈中弹出项目,从而以与您希望的顺序相反的顺序将它们提供给您进入新堆栈。因此,执行此过程两次将导致堆栈的顺序正确。
Stack
构造函数是Stack(IEnumerablesource)
当然,当您迭代时Stack
的 IEnumerable或者:
同样,我们必须按照与迭代堆栈的输出相反的顺序遍历堆栈。
我怀疑这两种方法之间是否存在性能差异。
You can write this as an extension method as
This is necessary because the
Stack<T>
constructor that we are using here isStack<T>(IEnumerable<T> source)
and of course when you iterate over theIEnumerable<T>
implementation for aStack<T>
it is going to repeatedly pop items from the stack thus feeding them to you in reverse of the order that you want them to go onto the new stack. Therefore, doing this process twice will result in the stack being in the correct order.Alternatively:
Again, we have to walk the stack in the reverse order from the output from iterating over the stack.
I doubt there is a performance difference between these two methods.
对于那些关心性能的人来说..还有其他一些方法可以在不造成性能损失的情况下迭代原始堆栈成员:
我编写了一个粗略的程序(链接将在帖子末尾提供)来测量性能并为已建议的实现添加了两个测试(请参阅Clone1和Clone2),以及针对ToArray和CopyTo 方法(参见Clone3和Clone4,它们都使用更高效的Array.Reverse方法)。
结果是:
正如我们所看到的,使用 CopyTo 的方法 方法速度快了 8 倍,同时实现也非常简单明了。此外,我对堆栈大小的最大值进行了快速研究:在发生 OutOfMemoryException 之前,Clone3 和 Clone4 测试适用于更大的堆栈大小:
上述 Clone1 和 Clone2 的结果较小,因为显式/隐式定义了额外的集合,因此影响了内存消耗。因此,Clone3 和 Clone4 方法允许更快地克隆堆栈实例并且占用更少的内存分配。使用反射可以获得更好的结果,但这是一个不同的故事:)
完整的程序列表可以在这里找到< /a>.
For those who take care of performance.. There are a few other ways how to iterate through the original stack members without big losses in the performance:
I wrote a rough program (the link will be provided at the end of the post) to measure performance and added two tests for the already suggested implementations (see Clone1 and Clone2), and two tests for ToArray and CopyTo approaches (see Clone3 and Clone4, both of them use more efficient Array.Reverse method).
The results are:
As we can see, the approach using CopyTo method is 8 times faster and at the same time the implementation is pretty simple and straightforward. Moreover, I did a quick research on a maximum value of stack size: Clone3 and Clone4 tests worked for bigger stack sizes before OutOfMemoryException occurs:
The results above for Clone1 and Clone2 are smaller due to additional collections that were explicitly/implicitly defined and therefore affected memory consumption. Thus, Clone3 and Clone4 approaches allow to clone a stack instance faster and with less memory allocations. You can gain even better results using Reflection, but it's a different story :)
The full program listing can be found here.
这是一种简单的方法,使用 LINQ:
您可以创建一个扩展方法来简化此操作:
用法:
Here's one easy way, using LINQ:
You could create an extension method to make this easier:
Usage:
如果您不需要实际的
Stack`1
,而只是想要现有Stack`1
的快速副本,您可以按照与相同的顺序遍历Pop
返回,另一个选择是将Stack`1
复制到Queue`1
中。然后,这些元素将以与从原始Stack`1
中弹出
相同的顺序出列
。输出:
If you don't need an actual
Stack`1
, but just want a quick copy of an existingStack`1
that you can walk in the same order thatPop
returns, another option is to duplicate theStack`1
into aQueue`1
. The elements will thenDequeue
in the same order that they'llPop
from the originalStack`1
.Output: