List<T>.Insert vs Stack<T>.Push
I am returning a IList<T>
from a method.
In the calling class I want to insert a value at the start of the list/stack.
Inserting a value in List<T>
is slower than pushing a value in Stack<T>
. But to use stack I need to unbox it.
So the question is which one is better, unbox or using Insert
in List<T>
? Which one is costlier?
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开发者_开发技巧
}
You're not unboxing here in either version (though the first won't compile.. and the second would always fail at runtime) -
However, in either case, if you do the conversion, it will only work if the actual underlying implementation is that class.
If your method returns an IList<T>
, I'd strongly suggest sticking to IList<T>
members. Converting the results to a List<T>
or Stack<T>
(ie: whatever the internal implementation happens to be - which is not Stack<T>
since that doesn't implement IList<T>
) is very dangerous.
The main reason to return IList<T>
is to purposefully allow you to later change the internal implementation. Method1
, internally, might later change from List<T>
to some other IList<T>
, which would cause your code to break unexpectedly.
That being said, if you know that the internal implementation may be a certain type, you can check for it - but I wouldn't blindly cast.
Inserting a value in
List<T>
is slower than pushing a value inStack<T>
.
Yes, for the reason that inserting in a list is a different operation from pushing to a stack. When you insert a new item into the middle of a list, then entire array that comes afterward has to be shifted by one. This is an O(n) operation. Pushing to a stack just adds the value to the end of the internal array. This is cheap - O(1). The comparable operation is List<T>.Add
But I do think there is a misunderstanding here as to when to use which. There is no difference between a List<T>
and Stack<T>
implementation-wise or performance-wise for the same operation. The only difference is in the features each collection exposes. You can mimic popping to Stack<T>
in List<T>
by (adding to end of the list and by) removing from the end: list.RemoveAt(list.Count - 1)
. It's how you want to use it that matters here. If you are going to use List<T>
as a Stack<T>
then discard the former and always use the latter. It makes your intent clearer. You're less error prone in future thus.
But to use stack I need to unbox it.
There is no unboxing here. Unboxing is when you cast from a reference type (object
, IList<T>
) to a value type (like structs, enums). Stack<T>
is not a value type, hence there is no unboxing. Its just reference conversion, preserving the identity. It's as cheap as it can get.
So the question is which one is better, unbox or using
Insert
inList<T>
? Which one is costlier?
Your second code doesn't work.
Stack<T>
isn'tIList<T>
. So you have only one choice left.Insert
is definitely costlier, but that alone doesn't mean you should use aStack<T>
.Stack<T>
doesn't give you random access via indexes, removal from middle etc. But if all you need is aStack<T>
, stick to it.List<T>
is too general purpose with which you can do lot of things.
Bottom line: you either return Stack<T>
and use it (better performance), or you return IList<T>
and use it (more features). In the end, decide based on use first.
精彩评论