Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
636 views
in Technique[技术] by (71.8m points)

.net - Array.IsReadOnly inconsistent depending on interface implementation

A typed array implements both the System.Collections.IList and System.Collections.Generic.ICollection<T> interfaces, which both have their own IsReadOnly properties. But what on earth is going on here?

var array = new int[10];
Console.WriteLine(array.IsReadOnly); // prints "False"

var list = (System.Collections.IList)array;
Console.WriteLine(list.IsReadOnly); // prints "False"

var collection = (System.Collections.Generic.ICollection<int>)array;
Console.WriteLine(collection.IsReadOnly); // prints "True"

The IList view of the array behaves as I'd expect, returning the same as the array itself, however the ICollection<T> view of the array returns true.

Is there any rational explanation for this behaviour, or is it a compiler/CLR bug? (I'd be really surprised if it's the latter as you'd imagine this would have been found before now, but it's so counter-intuitive I can't think what the explanation could be...).

I'm using C#3.0/.NET 3.5 SP1.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

From MSDN:

IList is a descendant of the ICollection interface and is the base interface of all non-generic lists. IList implementations fall into three categories: read-only, fixed-size, and variable-size. A read-only IList cannot be modified. A fixed-size IList does not allow the addition or removal of elements, but it allows the modification of existing elements. A variable-size IList allows the addition, removal, and modification of elements.

The ICollection<T> interface does not have an indexer, so a fixed-size ICollection<T> is automatically readonly - there is no way to modify an existing item.

Possibly ICollection<T>.IsFixedSize would have been a better property name than ICollection<T>.IsReadOnly, but both imply the same thing - impossible to add or remove elements, i.e. the same as IList.IsFixedSize.

An array is a fixed-size list, but is not readonly as elements can be modified.

As an ICollection<T>, it is readonly, since an ICollection<T> has no way to modify elements.

This may appear confusing, but it is consistent and logical.

What is slightly inconsistent is that the generic IList<T> interface has an IsReadOnly property inherited from ICollection<T> whose semantics are therefore different from the non-generic IList.IsReadOnly. I imagine the designers were aware of this inconsistency but were unable to go back and change the semantics of the non-generic IList for backwards compatibility reasons.

To summarize, an IList can be:

  • Variable-size.

    IList.IsFixedSize = false

    IList.IsReadOnly = false

    ICollection<T>.IsReadOnly = false

  • Fixed-size (but elements can be modified, e.g. an Array)

    IList.IsFixedSize = true

    IList.IsReadOnly = false

    ICollection<T>.IsReadOnly = true

  • Read-only (elements can not be modified)

    IList.IsFixedSize = true

    IList.IsReadOnly = true

    ICollection<T>.IsReadOnly = true


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...