List <t> .Insert vs Stack <t> .Push </t> </t>

时间:2011-07-05 23:07:35

标签: c# .net performance generics

我从方法返回IList<T>

在调用类中,我想在列表/堆栈的开头插入一个值。

List<T>中插入值比在Stack<T>中推送值要慢。但是要使用堆栈,我需要将其拆箱。

所以问题是哪一个更好,取消框或在Insert中使用List<T>?哪一个更昂贵?

class MyClass 
{
}

IList<MyClass> Method1()
{
}

class MainClass
{
   List<MyClass> list = (List<MyClass>)Method1();
   list.insert(0,new MyClass{...}); //insert at the start. 

   Stack<MyClass> stack = (Stack<MyClass>)Method1();
   stack.Push(new MyClass{...}); //insert at the start
}

2 个答案:

答案 0 :(得分:3)

你在这两个版本中都没有取消装箱(虽然第一个不会编译..而第二个在运行时总是会失败) -

但是,在任何一种情况下,如果您进行转换,只有在实际的底层实现是该类时才会起作用。

如果您的方法返回IList<T>,我强烈建议坚持IList<T>成员。将结果转换为List<T>Stack<T>(即:无论内部实现是什么 - 不是Stack<T>,因为它没有实现IList<T>)是非常危险的

返回IList<T>的主要原因是故意让您稍后更改内部实现。内部Method1可能会稍后从List<T>更改为其他IList<T>,这会导致您的代码意外中断。

话虽如此,如果您知道内部实现可能是某种类型,您可以检查它 - 但我不会盲目地施放。

答案 1 :(得分:1)

  

List<T>中插入值比在Stack<T>中推送值要慢。

,因为在列表中插入与推送到堆栈的操作不同。当您将新项目插入列表中间时,之后出现的整个数组必须移动一个。这是O(n)操作。推送到堆栈只是将值添加到内部数组的末尾。这很便宜 - O(1)。可比较的操作是List<T>.Add

但我确实认为这里有什么误解。对于相同的操作,List<T>Stack<T>实现方式或性能方面没有区别。唯一的区别在于每个集合公开的功能。您可以模仿Stack<T>中的List<T>弹出(添加到列表的末尾,然后)从末尾删除list.RemoveAt(list.Count - 1)。这就是你想要如何使用它的重要性。如果您要将List<T>用作Stack<T>,则丢弃前者并始终使用后者。它使你的意图更清晰。因此,您将来不易出错。

  

但是要使用堆栈,我需要将其解包。

这里没有拆箱。取消装箱是指从引用类型(objectIList<T>)转换为值类型(如结构,枚举)。 Stack<T>不是值类型,因此没有取消装箱。它只是引用转换,保留了身份。它尽可能便宜。

  

所以问题是哪一个更好,取消框或在Insert中使用List<T>?哪一个更昂贵?

  • 你的第二个代码不起作用。 Stack<T>不是IList<T>。所以你只剩下一个选择。

  • Insert肯定更贵,但仅此并不意味着您应该使用Stack<T>Stack<T>并未通过索引向您提供随机访问权限,从中间删除等等。但如果您只需要Stack<T>,请坚持使用。 List<T>过于笼统,你可以做很多事情。

底线:您要么返回Stack<T>并使用它(更好的性能),要么返回IList<T>并使用它(更多功能)。最后,先根据用途决定。