An interesting discussion has been occurring in comments, and in this bug report, about the problems with IList and arrays that I discussed earlier.

I think the discussion has correctly focussed in on a key problem: that the IsReadOnly property on ICollection<T> is too general to take into account the different kinds of changes that can be made to a list. Having identified this problem, however, does not necessarily mean that we need to proliferate into a huge number of different “Is/Can” properties. Instead, we should look at the implementations that actually make sense and put in enough properties to handle the realistic cases.

In the case of ICollection<T> and IList<T>, my feeling is that two properties would handle all the interesting cases easily:

1. ICollection<T> should change IsReadOnly to CanAddRemove. If true, this would indicate that items can be added to or removed from the collection using the “Add”, “Remove”, and “Clear” methods on ICollection. If false, this would indicate that Add, Remove, and Clear should not be called (however, other methods of changing the collection might work).

2. IList<T> should add CanChangeValues to indicate that values in the list can be changed using the indexer. If true, the set accessor on the indexer can be used to change the value at a particular index. If false, the set accessor on the indexer should not be used. If both CanAddRemove and CanChangeValues are true, then Insert and RemoveAt can be used to insert or remove values at a particular place.

These two properties allow all of the interesting cases that I can think of:

read/write List<T>: CanAddRemove=true, CanChangeValues=true

read/write array: CannAddRemove=false, CanChangeValues=true

read-only List<T>: CanAddRemove=false, CanChangeValues=false

OrderedSet<T>: CanAddRemove=true, CanChangeValues=false (This is the case where items can be added to the collection, but the order in the collection is fixed by the values. Thus, you cannot change the value at a particular index, or insert at a particular index, but you can add or remove values at an unspecified location).

[For similar reasons, IDictionary<K,V> should include a CanChangeValues that indicates whether the value associated with a key can be changed. This allows the case where a dictionary as a fixed set of keys, but the values associated with the keys can be changed.]