The indexer is implemented with explicit interface implementation, so you'll only be able to access it if you do:
IList<int> b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;
or
var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
((IList<int>)b)[2] = 3;
Of course, it'll then fail at execution time...
This is entirely deliberate and helpful - it means that when the compiler knows it's a ReadOnlyCollection
, the unsupported bits of functionality aren't available to you, helping to divert you away from execution time failure.
It's an interesting and relatively unusual step though, effectively implementing one half of a property/indexer implicitly, and one half explicitly.
Contrary to my previous thoughts, I believe ReadOnlyCollection<T>
actually implements the whole indexer explicitly, but also provides a public readonly indexer. In other words, it's something like this:
T IList<T>.this[int index]
{
// Delegate interface implementation to "normal" implementation
get { return this[index]; }
set { throw new NotSupportedException("Collection is read-only."); }
}
public T this[int index]
{
get { return ...; }
}