views:

879

answers:

6

I have a class named Customer (with typical customer properties) and I need to pass around, and databind, a "chunk" of Customer instances. Currently I'm using an array of Customer, but I've also used Collection of T (and List of T before I knew about Collection of T). I'd like the thinnest way to pass this chunk around using C# and .NET 3.5.

Currently, the array of Customer is working just fine for me. It data binds well and seems to be as lightweight as it gets. I don't need the stuff List of T offers and Collection of T still seems like overkill. The array does require that I know ahead of time how many Customers I'm adding to the chunk, but I always know that in advance (given rows in a page, for example).

Am I missing something fundamental or is the array of Customer OK? Is there a tradeoff I'm missing.

Also, I'm assuming that Collection of T makes the old loosely-typed ArrayList obsolete. Am I right there?

Thanks

+6  A: 

Yes, Collection<T> (or List<T> more commonly) makes ArrayList pretty much obsolete. In particular, I believe ArrayList isn't even supported in Silverlight 2.

Arrays are okay in some cases, but should be considered somewhat harmful - they have various disadvantages. (They're at the heart of the implementation of most collections, of course...) I'd go into more details, but Eric Lippert does it so much better than I ever could in the article referenced by the link. I would summarise it here, but that's quite hard to do. It really is worth just reading the whole post.

Jon Skeet
He does do a great job in that article, a good read for anyone who hasn't already.
Quintin Robinson
+3  A: 

Generally, you should 'pass around' IEnumerable<T> or ICollection<T> (depending on whether it makes sense for your consumer to add items).

Alun Harford
A: 

I'm going to put in a dissenting argument to both Jon and Eric Lippert )which means that you should be very weary of my answer, indeed!).

The heart of Eric Lippert's arguments against arrays is that the contents are immutable, while the data structure itself is not. With regards to returning them from methods, the contents of a List are just as mutable. In fact, because you can add or subtract elements from a List, I would argue that this makes the return value more mutable than an array.

The other reason I'm fond of Arrays is because sometime back I had a small section of performance critical code, so I benchmarked the performance characteristics of the two, and arrays blew Lists out of the water. Now, let me caveat this by saying it was a narrow test for how I was going to use them in a specific situation, and it goes against what I understand of both, but the numbers were wildly different.

Anyway, listen to Jon and Eric =), and I agree that List almost always makes more sense.

Travis
There are certainly places where it makes sense to use arrays, and they will indeed perform better. That's a reason to use them *where performance is critical* (which isn't many places IME). For the immutability argument: if you declare that a method returns Foo[] then it will *always* be mutable.
Jon Skeet
If, on the other hand, you declare that it returns IList<T> then the returned value *can* be mutable or it *can* be immutable - and you can very easily build a read-only wrapper. It's not so much a case of "array vs List<T>" as "array vs an interface" for return types.
Jon Skeet
Couldn't you return an Array of IImmutableObject[], though? I'm not trying to be argumentative, but that argument has never made sense to me.(In case anyone finds my argument compelling, please use List<T>, as it is the right thing to do in 99.9% of cases).
Travis
If you return IImmutableObject[], I can still do: IImmutableObject[] foo = GetArray(); foo[0] = new ImutableObjectImpl(); - I've still changed the contents of the array.
Jon Skeet
You can do that with List<T> as well - but you *can't* do it if an immutable collection (e.g. ReadOnlyCollection<T>) is returned. With IList<T> you can *try* to do it, but the implementation may throw an exception at execution time.
Jon Skeet
A: 

I agree with Alun, with one addition. If you may want to address the return value by subscript myArray[n], then use an IList.

An Array inherently supports IList (as well as IEnumerable and ICollection, for that matter). So if you pass by interface, you can still use the array as your underlying data structure. In this way, the methods that you are passing the array into don't have to "know" that the underlying datastructure is an array:

        public void Test()
{
 IList<Item> test = MyMethod();
}

public IList<Item> MyMethod()
{
 Item[] items = new Item[] {new Item()};
 return items;
}
JMarsch
+1  A: 

If you have an immutable list of customers, that is... your list of customers will not change, it's relatively small, and you will always iterate over it first to last and you don't need to add to the list or remove from it, then an array is probably just fine.

If you're unsure, however, then your best bet is a collection of some type. What collection you choose depends on the operations you wish to perform on it. Collections are all about inserts, manipulations, lookups, and deletes. If you do frequent frequent searches for a given element, then a dictionary may be best. If you need to sort the data, then perhaps a SortedList will work better.

I wouldn't worry about "lightweight", unless you're talking a massive number of elements, and even then the advantages of O(1) lookups outweigh the costs of resources.

When you "pass around" a collection, you're only passing a reference, which is basically a pointer. So there is no performance difference between passing a collection and an array.

Mystere Man
+4  A: 

No one has mentioned the Framework Guidelines advice: Don't use List<T> in public API's:

We don’t recommend using List in public APIs for two reasons.

  • List<T> is not designed to be extended. i.e. you cannot override any members. This for example means that an object returning List<T> from a property won’t be able to get notified when the collection is modified. Collection<T> lets you overrides SetItem protected member to get “notified” when a new items is added or an existing item is changed.

  • List has lots of members that are not relevant in many scenarios. We say that List<T> is too “busy” for public object models. Imagine ListView.Items property returning List<T> with all its richness. Now, look at the actual ListView.Items return type; it’s way simpler and similar to Collection<T> or ReadOnlyCollection<T>

Also, if your goal is two-way Databinding, have a look at BindingList<T> (with the caveat that it is not sortable 'out of the box'!)

Mitch Wheat