为什么((IList <T>)数组).ReadOnly = True但是((IList)数组).ReadOnly = False?

J S*_*ith 21 .net c# arrays generics

我知道在.NET中,所有数组都派生自System.Array并且System.Array类实现IList,ICollectionIEnumerable.实际的数组类型也实现IList<T>,ICollection<T>IEnumerable<T>.

这意味着如果你有一个String[],那么那个String[]对象也是a System.Collections.IList和a System.Collections.Generic.IList<String>;.

不难看出为什么那些IList会被认为是"ReadOnly",但令人惊讶的是......

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

在这两种情况下,尝试通过Remove()RemoveAt()方法删除项会导致NotSupportedException.这表明两个表达式都对应于ReadOnly列表,但IList的ReadOnly属性不返回预期值.

怎么会?

Jon*_*eet 11

这看起来像一个普通的错误:

  • 它显然不是只读的,因为索引器允许它被修改
  • 没有执行到任何其他类型对象的转换

请注意,您不需要强制转换 - 存在隐式转换:

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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

ICollection<T>.IsReadOnly(从中IList<T>继承属性)记录为:

只读集合不允许在创建集合后添加,删除或修改元素.

虽然阵列不允许元素的添加或移除,它清楚地确实允许修改.

  • @supercat:这正是我之前提到的问题。基本上“IsReadOnly”并没有真正给你任何有用的东西,即使你相信它的话。无论如何,我认为我们在这里的评论有些过分了。我仍然认为它的设计很糟糕,并且根据糟糕的文档,数组的实现被破坏了。 (2认同)

Mar*_*ila 11

来自MSDN:

Array实现IsReadOnly属性,因为System.Collections.IList接口需要它.只读数组不允许在创建数组后添加,删除或修改元素.

如果需要只读集合,请使用实现System.Collections.IList接口的System.Collections类.

如果将数组转换或转换为IList接口对象,则IList.IsReadOnly属性将返回false.但是,如果将数组转换或转换为IList <T>接口,则IsReadOnly属性将返回true.

这里只读意味着数组中的项目无法修改,这就是它返回false的原因.

另外看看Array.IsReadOnly根据接口实现的不一致.

  • 虽然我很感激你只是引用,但“只读数组”这句话对我来说毫无意义……唯一不可变的数组是一个空数组。*所有* 数组都允许在创建数组后修改元素。我的回答给出了一个修改所谓只读列表的示例。`Array.IsReadOnly` 只不过说明了 `IList` 和 `IList&lt;T&gt;` 实现之间的不一致。对我来说仍然看起来像一个错误。 (2认同)