views:

3323

answers:

9

I often use an ArrayList instead of a 'normal' array[].

I feel as if I am cheating (or being lazy) when I use an ArrayList, when is it okay to use an ArrayList over an array?

+2  A: 

Unless that part of the code is absolutely performance-critical, using ArrayList is perfectly fine.

Michael Borgwardt
Well, in 1.1 maybe... you should generally aim for List<T> in 2.0
Marc Gravell
+32  A: 

Arrays are strongly typed, and work well as parameters. If you know the length of your collection and it is fixed, you should use an array.

ArrayLists are not strongly typed, every Insertion or Retrial will need a cast to get back to your original type. If you need a method to take a list of a specific type, ArrayLists fall short because you could pass in an ArrayList containing any type. ArrayLists use a dynamically expanding array internally, so there is also a hit to expand the size of the internal array when it hits its capacity.

What you really want to use is a generic list like List<T>. This has all the advantages of Array and ArrayLists. It is strongly typed and it supports a variable length of items.

Bob
An ArrayList doesn't use a LinkedList as the internal data structure! It uses a vector which is an array that is dynamically resized on add/insert/delete operations.
Alex
Good catch, It has been a while since I looked that up. I corrected the answer.
Bob
+4  A: 

Better still, wherever you use ArrayList, use the List<T> generic collection instead. It is more strongly typed than the former.

Frederick
A: 

Well for one, if you only intend to handle a specific type, you shouldn't use an ArrayList. For example, if you only expect an array of bytes, you should only accept an array of bytes.

Only time I would think you may even think of using an ArrayList is instead of List.

Spodi
+7  A: 

In addition to Bob's and Frederick's response, I would like to point it out that while arrays have covariance, generic lists do not. For example, an array of type MyChildClass[] can be easily casted to MyParentClass[], while List<MyChildClass> cannot be casted to List<MyParentClass>, at least not directly.

If you need covariance, either use arrays, use LINQ's Cast() method or some other means to cast each item individually or wait for C# 4.

DrJokepu
C# 4 will not offer covariance for lists - only IEnumerable<T> (and a few delegates) - it demands strict "in" *xor* "out" usage, and List<T> has both "in" *and* "out" usage.
Marc Gravell
Marc: I see, thanks for the clarification.
DrJokepu
A: 

The array's size is static, so if you do know the size at design time, use array. It is supposed to work faster, but I haven't tested it myself. If you need to change the count of objects frequently (adding or removing objects from the collection) use ArrayList or better the generic List from .NET 2. It's also easier to use, so if performance is not crucial, you can always use List.

Rumen Georgiev
+4  A: 

One other thought here is mutation; an array (T[]) is fully mutable, and cannot be protected. List<T> doesn't provide any useful extension points, but things like Collection<T> (or many other IList<T> implementations) allow you to add code, for example, to check items before they are added; likewise, you can have readonly IList<T> implementations, which is useful for thread safety where immutability is desirable.

I tend to use arrays either in internal method logic (perhaps as a local variable), as params arguments, or in a few highly optimised cases where I know the length of the items, and I know the code chooses not to mutate it (as a private field). Other than that, List<T> etc tend to be more common, as they have much less overhead when adding/removing items.

Marc Gravell
+1  A: 

I'm answering this from a Java perspective, but it's the same basic issue. You should not feel guilty using higher abstractions. After all, you are using Strings instead of char[], or even byte[]? I'd even suggest to go one step further and use the List interface where possible. The only reason to go one step down is for performance reasons.

Using the higher collection abstraction has many advantages. You can add decorators to make the List read-only, make it fixed size, check items that enter or leave the collection or use views (see GetRange in C# and subList in Java.)

By the way, an ArrayList should always be based on a primitive array, otherwise the name is wrong. The operations are usually implemented just how you would expect when using a primitive array. If a linked list is used it's usually named just that -- LinkedList. That's also an advantage of using the interface: You can change your mind about the used implementation later on.

There are a few things that make the use of collections clunky. One caveat is that the collections are usually based on objects, and the languages have a considerable gap between primitive and object types. The limited generics don't help much either. Still, I recommend the collections over arrays unless there's a good reason otherwise.

For primitive values you may also consider using a primitive collection library, for example GNU Trove. Don't know if there's anything similar for C#, though.

Ronald Blaschke
+1  A: 

Fabulous Adventures In Coding has written a piece Arrays considered somewhat harmful. It's a really interesting read.

doekman