Why does ((IList<T>)array).ReadOnly = True but ((IList)array).ReadOnly = False?

I know that in .NET all arrays derive from System.Array and that the System.Array class implements IList, ICollection and IEnumerable. Actual array types also implement IList<T>, ICollection<T> and IEnumerable<T>.

This means that if you have, for example, a String[], then that String[] object is also a System.Collections.IList and a System.Collections.Generic.IList<String>;.

It's not hard to see why those IList's would be considered "ReadOnly", but surprisingly...

String[] array = new String[0];
Console.WriteLine(((IList<String>)array).IsReadOnly); // True
Console.WriteLine(((IList)array).IsReadOnly); // False!

In both cases, attempts to remove items via the Remove() and RemoveAt() methods results in a NotSupportedException. This would suggest that both expressions correspond to ReadOnly lists, but IList's ReadOnly property does not return the expected value.

How come?

Jon Skeet
people
quotationmark

This looks like a plain bug to me:

  • It clearly isn't read-only, as the indexer allows it to be modified
  • It is not performing a conversion to any other kind of object

Note that you don't need to cast - there's an implicit conversion:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        string[] array = new string[1];
        IList<string> list = array;
        Console.WriteLine(object.ReferenceEquals(array, list));
        Console.WriteLine(list.IsReadOnly);
        list[0] = "foo";
        Console.WriteLine(list[0]);
    }
}

ICollection<T>.IsReadOnly (which IList<T> inherits the property from) is documented as:

A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.

While an array doesn't allow the addition or removal of elements, it clearly does allow modification.

people

See more on this question at Stackoverflow