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)
ICollection<T> is an interface, List<T> is a class.
Generic. ICollection<T> interface. The ICollection interface extends IEnumerable; IDictionary and IList are more specialized interfaces that extend ICollection. An IDictionary implementation is a collection of key/value pairs, like the Hashtable class.
IEnumerable has one property: Current, which returns the current element. ICollection implements IEnumerable and adds few additional properties the most use of which is Count. The generic version of ICollection implements the Add() and Remove() methods.
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.
ICollection does not have a guaranteed order, but the class that actually implements it may (or may not).
If you want to return an ordered collection, then return an IList<T>
and don't get too hung up on FxCop's generally sound, but very generic, advice.
No, ICollection does not imply an order.
The ICollection
instance has the "order" of whatever class that implements it. That is, referencing a List<T>
as an ICollection
will not alter its order at all.
Likewise, if you access an unordered collection as an ICollection
, it will not impose an order on the unordered collection either.
So, to your question:
Does an ICollection even have an order?
The answer is: it depends solely on the class that implements it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With