Almost any collection should provide a means to allow its creation from other common collections or to allow it to be made into (or even better treated like) other common collections.
Arrays are powerful but complex to reason about since they are (inherently) mutable but that allows some powerful optimizations where needed (for example efficient quicksort implementations really need to be able to swap elements in place).
Sequences (IEnumerable<T>
to you) are excellent since they mandate so little about themselves (including crucially any way to modify them) meaning code expecting them tends to be very flexible and widely useful.
Being able to simply and easily get to a particular sort of collection from another one allows you to write code to that works on the structures it needs but easily interact with many other sorts of structures with a simple translation call. If this turns out later to be a performance issue you may have to avoid the translation and make more of the code base know about the underlying types but to start with you can write it cleanly and quickly.
A great many api's already exist which expect a certain sort of collection, possible reasons include:
- Written before the 2.0 changes that made collections much richer in .Net
- Because they know they need to mutate state they make the caller responsible for providing
the state to be altered (things like sort in place functions)
- They were written poorly
It's worth noting that the lack of any sort of strongly typed collection in .Net pre 2.0 apart from arrays means that many BCL api's are, with hindsight, poorly designed. The reflection api's in the BCL are notable examples returning arrays all over the place when they should be IEnumerable's.
As such being able to easily transition from one sort of explicit collection to another is very useful in the real world.
Rereading your statement (it's not really a question at the moment) it appears you are actually confused about whether or not we should require explicit casting/conversion methods when transitioning from one collection to another.
The answer to that is, it depends (and dynamic does change things somewhat but not by much).
Simply put if a collection instance can be transparently treated like the expected type no conversion should be required. In general functions should try to request as little as possible (IEnumerable normally) and then whatever actual type passed in will function fine via polymorphism. In some cases the runtime has to do some magic to make this happen (arrays being a notable example of this) but normally this is just fine.
Where things get complex is where functions require concrete types. Again poor design upfront like failing to include an ISet interface when adding HashSet means that if you have a method that really needs a set you are forced to go with a concrete type or roll your own ISet and backing Set - not pleasant. Certain conversions operations, say from a set to a list are feasible in a read only context (you simply deterministically enumerate across all values in the set) but not in a write context (you could add something to a list twice but not a set for example)
This is where the common functional convention on almost everything being immutable helps, by doing this it becomes far easier to not care too much about the concrete implementation of the collection and think solely about it's externally visible behaviour (a red balck tree for a set or a hashtable - it doesn't matter to consumers its just a set)
Dynamic makes things somewhat complex since to keep the (roughly stated) 'axiom' of it's implementation that when using dynamic you should get the same result as if the static typing had been present it must deal with cases like the runtime magic on arrays.