Following the rules that a public APIs should never return a list, i'm blinding converting all code that returned lists, to return ICollection<T>
instead:
public IList<T> CommaSeparate(String value) {...}
becomes
public ICollection<T> CommaSeparate(String value) {...}
And although an ICollection
has a Count
, there is no way to get items by that index.
And although an ICollection
exposes an enumerator (allowing foreach
), i see no guarantee that the order of enumeration starts at the "top" of the list, as opposed to the "bottom".
i could mitigate this by avoiding the use of ICollection
, and instead use Collection
:
public Collection<T> Commaseparate(String value) {...}
This allows the use of an Items[index]
syntax.
Unfortunately, my internal implementation constructs an array; which i can be cast to return IList
or ICollection
, but not as a Collection
.
Is there a ways to access items of a collection in order?
This begs the wider question: Does an ICollection even have an order?
Conceptually, imagine i want to parse a command line string. It is critical that the order of items be maintained.
Conceptually, i require a contract that indicates an "ordered" set of string tuples. In the case of an API contract, to indicate order, which of the following is correct:
IEnumerable<String> Grob(string s)
ICollection<String> Grob(string s)
IList<String> Grob(string s)
Collection<String> Grob(string s)
List<String> Grob(string s)
The ICollection<T>
interface doesn't specify anything about an order. The objects will be in the order specified by the object returned. For example, if you return the Values
collection of a SortedDictionary
, the objects will be in the the order defined by the dictionary's comparer.
If you need the method to return, by contract, a type whose contract requires a certain order, then you should express that in the method's signature by returning the more specific type.
Regardless of the runtime type of the object returned, consider the behavior when the static reference is IList<T>
or ICollection<T>
: When you call GetEnumerator()
(perhaps implicitly in a foreach loop), you're going to call the same method and get the same object regardless of the static type of the reference. It will therefore behave the same way regardless of the CommaSeparate()
method's return type.
Additional thought:
As someone else pointed out, the FXCop rule warns against using List<T>
, not IList<T>
; the question you linked to is asking why FXCop doesn't recommend using IList<T>
in place of List<T>
, which is another matter. If I imagine that you are parsing a command-line string where order is important, I would stick with IList<T>
if I were you.