Array.IsReadOnly不一致,具体取决于接口实现

Gre*_*ech 5 .net .net-3.5 c#-3.0

一个类型数组同时实现System.Collections.IListSystem.Collections.Generic.ICollection<T>接口,都有自己的IsReadOnly特性.但到底是怎么回事?

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"
Run Code Online (Sandbox Code Playgroud)

IList阵列的视图表现为我预计,返回相同的阵列本身,但是ICollection<T>该阵列的视图返回true.

这种行为有没有合理的解释,还是编译器/ CLR错误?(如果是后者,我会感到非常惊讶,因为你会想象之前会发现这种情况,但这是违反直觉的,我无法想到解释可能是什么......).

我正在使用C#3.0/.NET 3.5 SP1.

Joe*_*Joe 6

来自MSDN:

IList是ICollection接口的后代,是所有非泛型列表的基本接口.IList实现分为三类:只读,固定大小和可变大小.无法修改只读IList.固定大小的IList不允许添加或删除元素,但它允许修改现有元素.可变大小的IList允许添加,删除和修改元素.

ICollection <T>接口没有索引器,因此固定大小的ICollection <T>会自动只读 - 无法修改现有项目.

可能ICollection <T> .IsFixedSize是一个比ICollection <T> .IsReadOnly更好的属性名,但两者都暗示相同的东西 - 不可能添加或删除元素,即与IList.IsFixedSize相同.

数组是固定大小的列表,但由于元素可以修改,因此不是只读的.

作为ICollection <T>,它是只读的,因为ICollection <T>无法修改元素.

这可能看起来令人困惑,但它是一致和合乎逻辑的.

稍微不一致的是,通用IList <T>接口具有从ICollection <T>继承的IsReadOnly属性,因此其语义与非通用IList.IsReadOnly不同.我想设计师已经意识到这种不一致性,但由于向后兼容的原因,他们无法返回并更改非通用IList的语义.

总而言之,IList可以是:

  • 可变大小.

    IList.IsFixedSize = false

    IList.IsReadOnly = false

    ICollection <T> .IsReadOnly = false

  • 固定大小(但可以修改元素,例如数组)

    IList.IsFixedSize = true

    IList.IsReadOnly = false

    ICollection <T> .IsReadOnly = true

  • 只读(元素无法修改)

    IList.IsFixedSize = true

    IList.IsReadOnly = true

    ICollection <T> .IsReadOnly = true


Han*_*ant 4

正如这篇反馈文章的评论所表明的那样,这个决定引起了很多痛苦。

  • 反馈文章的链接似乎已损坏。还有另一个链接吗? (3认同)