列表<;T>;.插入与堆叠<;T>;.推动
本文关键字:gt lt 推动 列表 插入 | 更新日期: 2023-09-27 18:01:08
我从一个方法返回一个IList<T>
。
在调用类中,我想在列表/堆栈的开头插入一个值。
在List<T>
中插入值比在Stack<T>
中推送值慢。但要使用堆栈,我需要将其开箱。
那么问题是,开箱还是在List<T>
中使用Insert
,哪个更好?哪一个更贵?
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
}
在这两个版本中都没有开箱(尽管第一个版本不会编译..第二个版本在运行时总是失败(-
然而,在任何一种情况下,如果进行转换,则只有当实际的底层实现是该类时,才会起作用。
如果您的方法返回IList<T>
,我强烈建议您坚持使用IList<T>
成员。将结果转换为List<T>
或Stack<T>
(即:无论内部实现是什么——它不是Stack<T>
,因为它没有实现IList<T>
(是非常危险的。
返回IList<T>
的主要原因是有目的地允许您稍后更改内部实现。Method1
在内部可能稍后从List<T>
更改为其他IList<T>
,这将导致代码意外中断。
话虽如此,如果你知道内部实现可能是某种类型,你可以检查它——但我不会盲目地强制转换。
在
List<T>
中插入值比在Stack<T>
中推送值慢
是,因为在列表中插入与推送到堆栈是不同的操作。当您将一个新项目插入列表的中间时,随后出现的整个数组必须偏移一个。这是一个O(n(运算。推到堆栈只会将值添加到内部数组的末尾。这是便宜的-O(1(。类似的操作是List<T>.Add
但我确实认为在什么时候使用哪个方面存在误解。对于相同的操作,List<T>
和Stack<T>
在实现方面或性能方面没有区别。唯一的区别在于每个集合公开的功能。您可以模拟在List<T>
中弹出到Stack<T>
,方法是(添加到列表末尾,然后从末尾删除:list.RemoveAt(list.Count - 1)
。在这里,重要的是你想如何使用它。如果要将List<T>
用作Stack<T>
,则放弃前者,始终使用后者。这会让你的意图更加清晰。这样一来,你以后就不那么容易出错了。
但要使用堆栈,我需要将其开箱。
这里没有开箱。取消装箱是指从引用类型(object
、IList<T>
(强制转换为值类型(如structs、enums(。Stack<T>
不是值类型,因此没有取消装箱。它只是引用转换,保留身份。它尽可能便宜。
所以问题是,开箱还是在
List<T>
中使用Insert
哪个更好?哪一个更贵
-
您的第二个代码不起作用。
Stack<T>
不是IList<T>
。所以你只有一个选择了。 -
Insert
肯定更贵,但这并不意味着你应该使用Stack<T>
。Stack<T>
不会通过索引、从中间删除等方式为您提供随机访问。但如果您只需要一个Stack<T>
,请坚持使用。List<T>
的用途太通用,您可以做很多事情。
一句话:您要么返回Stack<T>
并使用它(更好的性能(,要么返回IList<T>
并使用它。最后,先根据使用情况决定。