TommyCarlier said:
TommyCarlier said:
*snip*

Actually, now that I think about it further: it could be a good idea to move all the members of ICollection<T> and IList<T> that can be performed on read-only collections to interfaces IReadOnlyCollection<T> and IReadOnlyList<T>. It would allow for richer API's without additional overhead. The current collection classes would not have to be changed. The only thing that changes is the addition of these interfaces and the modification of ICollection<T> and IList<T> (so they implement IReadOnlyCollection<T> and IReadOnlyList<T>).

The interface hierarchy would look like this:
 public interface IEnumerable<T> : IEnumerable {   IEnumerator<T> GetEnumerator(); } public interface IReadOnlyCollection<T> : IEnumerable<T> {   int Count { get; }   bool Contains(T item);
   void CopyTo(T[] array, int arrayIndex); } public interface IReadOnlyList<T> : IReadOnlyCollection<T> {   T this[int index] { get; }   int IndexOf(T item); } public interface ICollection<T> : IReadOnlyCollection<T> {   void Add(T item);   void Clear();   bool
 Remove(T item);   bool IsReadOnly { get; } } public interface IList<T> : ICollection<T>, IReadOnlyList<T> {   void Insert(int index, T item);   void RemoveAt(int index);   T this[int index] { get; set; } }

(Edit: I was tired and I screwed up the example a bit. All fixed now)

Given the work they are doing around covariance and contravariance in 4.0, I think this idea makes a lot of sense. It makes so much sense that I think the only reason they might not do it is for reasons of backwards compatibility (I have no idea if that would be an issue or not). To take this to an insane level, what about splitting the interfaces between IReadOnlyBlah and IMutableBlah and an IBlah that derives and unifies both? Why IMutableBlah? Suppose:

class Foo : Bar
{
    ...
}

void PopulateFoos(IMutableCollection<Foo> foos)
{
    ...
}

with contravariance I can do this:

var bars = new List<Bar>();
...
PopulateFoos(bars); // Look, Ma! No casting or converting!