我觉得使用GetEnumerator()并投射IEnumerator.Current是很昂贵的。有什么更好的建议吗?
如果它提供具有更好性能的类似功能,我愿意使用不同的数据结构。
思考后:
泛型堆栈是否更好,以便不需要强制转换?
答案 0 :(得分:14)
Stack<T>
(使用foreach)确实可以保存演员表,但实际上是在{$ 3}}中装箱。如果您遇到性能问题,我怀疑这是您可以增加很多价值的领域。使用分析器,并专注于实际问题 - 否则这是不成熟的。
请注意,如果您只想读取一次数据(即您很乐意使用堆栈),那么可能更快(避免了枚举器的开销); YMMV。
Stack<T> stack = null;
while (stack.Count > 0)
{
T value = stack.Pop();
// process value
}
答案 1 :(得分:6)
你做过任何基准测试,还是只是直觉?
如果您认为大部分处理时间都花在循环堆栈上,那么您应该对其进行基准测试,并确保情况确实如此。如果是,您有几个选择。
编辑:
当您尝试在列表中进行查找或匹配两个列表或类似列表时,可能不需要的循环示例。如果循环需要很长时间,请查看将列表放入二叉树或哈希映射是否有意义。可能存在创建它们的初始成本,但是如果重新设计代码,则可以通过稍后进行O(1)查找来获得该代码。
答案 2 :(得分:5)
是的,使用通用堆栈将节省演员阵容。
答案 3 :(得分:4)
如果您需要Stack的功能(与List或其他一些colleciton类型相关),那么是的,使用通用堆栈。这会加快速度,因为编译器会在运行时跳过转换(因为它在编译时很流行)。
Stack<MyClass> stacky = new Stack<MyClass>();
foreach (MyClass item in stacky)
{
// this is as fast as you're going to get.
}
答案 4 :(得分:2)
枚举泛型IEnumerable<T>
或IEnumerator<T>
并不会创建强制转换,所以在大多数情况下使用泛型会更快,但是泛型有一些非常微妙的问题,特别是当与值类型一起使用时。
Rico Mariani(微软性能架构师)有一些帖子详细介绍了差异和基础
答案 5 :(得分:1)
就速度而言,有多个变量,取决于上下文。例如,在像C#这样的自动内存管理代码库中,您可以获得分配峰值,这可能会影响游戏等帧速率。你可以为这个而不是foreach做一个很好的优化是一个带有while循环的枚举器:
var enumerator = stack.GetEnumerator();
while(enumerator.MoveNext ()) {
// do stuff with enumerator value using enumerator.Current
enumerator.Current = blah
}
就CPU基准而言,这可能不比foreach快,但foreach可能会出现意外的分配峰值,最终可能会减慢&#34;你的申请表现。
答案 6 :(得分:0)
创建枚举器的另一种方法是使用ToArray方法,然后迭代数组。堆栈迭代器会导致一些轻微的开销,用于检查堆栈是否已被修改,而对阵列的迭代将很快。但是,当然首先要创建数组的开销。正如垫子所说,你应该对备选方案进行基准测试。