我从方法返回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
}
答案 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>
,则丢弃前者并始终使用后者。它使你的意图更清晰。因此,您将来不易出错。
但是要使用堆栈,我需要将其解包。
这里没有拆箱。取消装箱是指从引用类型(object
,IList<T>
)转换为值类型(如结构,枚举)。 Stack<T>
不是值类型,因此没有取消装箱。它只是引用转换,保留了身份。它尽可能便宜。
所以问题是哪一个更好,取消框或在
Insert
中使用List<T>
?哪一个更昂贵?
你的第二个代码不起作用。 Stack<T>
不是IList<T>
。所以你只剩下一个选择。
Insert
肯定更贵,但仅此并不意味着您应该使用Stack<T>
。 Stack<T>
并未通过索引向您提供随机访问权限,从中间删除等等。但如果您只需要Stack<T>
,请坚持使用。 List<T>
过于笼统,你可以做很多事情。
底线:您要么返回Stack<T>
并使用它(更好的性能),要么返回IList<T>
并使用它(更多功能)。最后,先根据用途决定。