views:

360

answers:

8

I was wondering which type would have better performance and which you think should be used.

For example I have a List of strings not knowing how many items I will need so having the .Add(String) function is really convenient. I can Add new strings to the list at any time easily.

What are the advantages/disadvantages of using each?

Are lists the new arrays?

+11  A: 

List<String> is implemented using an array String[].

If you don't know how many elements you'll have, use List<String>

You can give the estimated (or maximum) number of elements you expect in the capacity constructor parameter (new List<String>(10)), this will be the initial size of the underlying array.

When you Add() an item and there is no room for this item, the underlying array is copied to a new array of double the size.

What I do: when I know the exact size of the collection and I know I won't change the size of the collection, I use an array (String[]). Otherwise I use a List<String>.

By the way, this goes for any type and not just String.

brickner
+1. for mentioning List initial capacity.
Mitch Wheat
ditto. Good 'real world' rationale
KP
+5  A: 

It depends on usage scenario, BUT it's also a micro-optimisation until you have identified a bottleneck by profiling. Use whatever fits the usage best.

Mitch Wheat
+1  A: 

If you don't know the size of items to be added, always go for List<string> than string array.

Srinivas Reddy Thatiparthy
+1  A: 

If you need dynamic sizing, then go with List<string>.

If you're worried about performance, then I would suggest starting with List<string> and see if there's really an issue. It uses arrays internally so I would think, for the most part, there should be no performance issues.

If you have a staticly sized collection, you could still use string[].

Justin Niessner
+1  A: 

Of course it depends on your application, but in circumstances List<string> (or even just IEnumerable<string> is preferable.

Joel Coehoorn
+2  A: 

Use List<> in most all cases, and don't worry about performance. There is a good chance you will go through your entire career and never need to performance tune by converting a List<> into an array.

Brent Arias
+2  A: 

In most scenarios the performance difference is not appreciable so I would use List<string> since it provides much more functionality that could be useful in different situations.

Claudio Redi
+11  A: 

More context is really required to answer the question properly:

In a public API, you should try to use abstract collection types, so that you can change the internal implementation later if you need to.

  • If the collection should not be changed by the outside world, use IEnumerable<T>.
  • If the collection will be changed by the outside world, use ICollection<T>.
  • If indexed access is required, use IList<T>.

In a private implementation, it's not as important to use the abstract types:

  • If you need indexed access and know the final size, use T[] or List<T>.
  • If you need indexed access and don't know the final size, use List<T>.
  • If you plan to access elements in a LIFO pattern, use Stack<T>.
  • If you plan to access elements in a FIFO pattern, use Queue<T>.
  • If you need to access elements at the beginning and end of the list, but not in the middle, use LinkedList<T>.
  • If you don't want duplicates, use HashSet<T>.

In .NET 4.0 you have a few more choices, but those are the basics.

Aaronaught
"If the collection should not be changed by the outside world use IEnumerable<T>" - I disagree with this characterisation. Returning IEnumerable<T> won't help if the object referenced by the return value is a mutable list - the caller can always cast. You should return IEnumerable<T> if the caller should only be able to enumerate, ICollection<T> if he also needs a Count, and IList<T> if he will need indexed access. In **all** of the above cases, if the collection should not be changed by the outside world, wrap it in a readonly collection (e.g. using List<T>.AsReadOnly).
Joe
@Joe: I'm not a fan of that argument. The caller can always try to cast **anything** you give it to *anything* else - it's simply poor design to do so. You can wrap all results in a `ReadOnlyCollection<T>` if you want, but that won't protect you against *hostile* callers; they can just use Reflection to get at the internal mutable list. If this is ultra-secure code then the only way to guarantee this particular invariant is return a *new*, generated `IEnumerable<T>` instance, i.e. by returning `originalEnumerable.Select(x => x).ToArray()`.
Aaronaught
But in any event, the recommendations are from a discoverability and code-maintenance perspective (writing self-documenting code), not a security perspective; if you're in the latter camp then you have *many* other things to worry about. It's also the reason why I used the phrase "should not" as opposed to "must not" - it's not a guarantee, just a very strong hint. `ReadOnlyCollection<T>` will give a *runtime* error if a modification is attempted; you want to catch such errors at *compile-time* whenever possible.
Aaronaught