views:

1517

answers:

11

I was recently asking someone why he preferred to return a strongly-typed array over an IList. I had always thought that programming against an interface was the most flexible and best way program when faced with a project having a long life. So it struck me as odd when he replied:

We typically prefer immutable types over mutable ones. Arrays are immutable. IList is not.

I'm not entirely sure I understand this statement. Can anyone help clarify this?

Thanks for any help you guys can provide.

A: 

Perhaps this someone does not know what he is talking about?

Brian
I doubt it. It's more likely that I don't know what "he's" talking about lol.
mkelley33
A: 

Basically he's saying "we prefer structures which can't be changed easily at run time, because we believe them to be less vulnerable to errors." Whether that's correct in this case is another question.

Charlie Martin
Hmmm. I like that, but don't know if its more valuable than programming against an IList<T>, since I have more flexibility over the implementation. Thanks for the help. That makes his position a little clearer.
mkelley33
+2  A: 

I don't understand it either. Arrays are very much mutable, except for their size. Individual elements can still be modified. Maybe he meant arrays are value types and Lists are reference types. I don't know.

Anyway, you should probably have a look at Eric Lippert's opinion on the subject. Could provide you with some ammo for discussion, too.

Rik
Thank you. I've read that article, thus the confusion lol. Given the varying opinions on the subject of mutability (what is and is not) I'd have to go with my gut instinct and return IList<T> until proven otherwise. Let me just say that I am totally indebted to the person that supplied the quote in this question's description. "He-who-must-not-be-name-out-of-respect" is an amazing coder and inspiration, but I don't blindly follow so I'll have to wait until I hear his rebuttle to the arguments provided here! Thanks again.
mkelley33
Thinking for yourself, good! :) Good luck convincing your friend.
Rik
+4  A: 

One point he could have meant is that IList includes the Insert, Remove, and Add methods, so the collection itself can be modified. T[], on the other hand, cannot have elements added to it.

I should add that FxCop recommends returning ReadOnlyCollection instead. The indexer is read-only, so you can't change the elements, and the Add and other such methods all throw NotSupportedException.

John Saunders
Cool! That's great. I use FxCop from time to time at my job, and I've always wondered about some of those recommendations. Thanks for the clarification!
mkelley33
A: 

Perhaps he meant the size of the array as "immutable"? Basically, you declare the size once and you're stuck with it. With lists, you can always use "Add".

I suppose that if you're sure about the size of the list, perhaps array is a bit faster?

luiscubal
That's exactly what I assumed, but I don't really know what that buys me when working with the repository pattern. Thanks!
mkelley33
A: 

Well. IList is mutable in the sense that you can add and remove items, rather than just change the items that are already there. An array lets you mess with individual items, but a particular index will never become entirely invalid. There's any number of reasons to prefer immutability -- it makes the surface area for accidental data corruption much smaller, for example.

Promit
Use ICollection<T>, and return one which is read-only if you return one. Arrays implement this interface, so that one can choose to pass interfaces or lists into such methods. Count, Add and Remove is defined on the generic ICollection<T> interface.
Lucero
+9  A: 

Whoever "he" is, is in 100% wrong on the topic. Arrays are a very much mutable. This is in fact one of the reasons not to return an array. There is no way to prevent a caller from changing the elements of an array to whatever they please.

The only way in which an Arrray is immutable is in it's length. Once an array is allocated, it's length cannot be changed. Even APIs such as Array.Resize don't actually resize the array, they just allocate a new one, copy the contents and return the new array (by reference in this case).

I do agree however that there are many cases in which it is better to return immutable data. The primary one is that it allows you to return a reference to an internal collection of a class without doing a complete copy and at the same time preventing the caller from messing with your internal state. Most mutable collections cannot make such guarantees.

JaredPar
"in which it is valid.." - do you mean "in which it is better"?
peterchen
@peterchen, yes, that's what I meant to say. corrected
JaredPar
Well, I wouldn't go that far..."He's" a really amazing coder, but I think he may be referring to some aspect in one of the comments below; however, I fail to see what this "buys" me or my program. If I'm using a repository pattern to return a list of objects, why must it be an array instead of IList<T>?
mkelley33
@mkelley33, which part are you talking about? He is certainly wrong about Arrays being immutable regardless of skill. They simple are mutable structures. This does not though make him less of a coder. Everyone is prone to mistakes (I myself try to make 2 or 3 a day) and this is one I've seen many people make. I would certainly argue for return an IList<T> over an array or better yet an actual immutable structure. It just gives you more flexibility over time.
JaredPar
Oh I don't think he's flawless by any means, but I think I may have quoted him out of context, though I'm still trying to understand the context. So I have an IRepository that has GetAll method returning IList<T>. How does immutability give you more flexibility over time? Thanks for all the help.
mkelley33
@mkelley, I meant more that returning an interface to a mutable or immutable collection gave you more flexibility over time.
JaredPar
+2  A: 

In principle he's right, but he doesn't know how to practice it properly...

We typically prefer immutable types over mutable ones.

That is correct. Immutable types are nicer to work with

Arrays are immutable. IList is not.

That is not correct. Neither of those are immutable.

If you want to return a collection that is immutable, return an IEnumerable<T> or a ReadOnlyCollection<T> (using the List<T>.AsReadOnly method). Still those doesn't protect the objects if they themselves are not immutable. Eventhough you can only read from the collections, you can still change the data in each object if they allow it.

Also, you should consider the "ownership" of the collection that you are returning. If you are creating an array for the sole purpose of returning it, then there is no reason not to give full control to it. If you on the other hand are returning a collection that is a member of the class, you should only allow as little access to it as is needed.

Guffa
+1  A: 

The reason to use an Interface as return type over the actual type itself, is to hide the internal implementation from the caller. This allowes the implementation to change the actual type without repurcusions to the rest of the application.

It does not make any sense to copy an internally used collection into an array for external use, for no other reason than mutable or immutable.

Seperate issues are: - return a list of strongly typed data or not. IList or IList. The use of strongly typed data is always preferred. - mutable or immutable. ICollection,IList or IEnumerator Return with what you want to allow to the data. For a readonly list return only a IEnumerator. If the caller is allowed to modify the collection use ICollection or IList.

Andre van Heerwaarde
+3  A: 

I think he maybe thought since an array's length property is immutable, then somehow arrays are more immutable than IList or maybe he used the wrong word and interchanged concrete with immutable. Who knows but it's an odd answer.

I think with returning a List there is something slightly implied that it's ok to modify it or that it may change while returning an array doesn't imply that as much.

For example, If you had an object model on top of a repository and had a method like GetCars() that returned a List and a junior programmer saw cars.Add(Car c) ... Would you think he was completely insane for thinking cars.Add(new Car()) might actually add a car into the repository? Arrays are just inherently more explicit.

I think List usage is more appropriate in properties, like Page.Controls.Add

I prefer returning arrays more often than List for several reasons.

  • Habit. Collections in 1.0/1.1 SUCKED

  • I prefer that my methods return the simplest & most lightweight object they can. If I need to make an Array a List it is trivial.

  • They can be used in .net 1.1 and it reduces the surface are of refactoring if I ever needed to support older versions of the runtime I can reuse at least some of my code or apply an identical object model.

Chad Grant
This gave me the "ah-ha" moment I was looking for! Returning T[] from a repository is less "leaky" (as in Law of Leaky Abstractions). If I wanted to add something to the repository, I would call it's Add/Insert method right? So it would be counterproductive/counter-intuitive for me to assume that adding something to the list returned would be able to participate in a Unit of Work or work as anticipated. When using an IRepository, he is 100% right! Albeit the explanation he gave me was more along the lines of what you said: Array is more immutable than IList in some regards. Thank you so much!
mkelley33
+2  A: 

I always prefer a ReadOnlyCollection. All the advantages of a List, but Read Only.

Michael Stum