Подтвердить что ты не робот

Почему массив ((IList <T>)).ReadOnly = True, но ((IList)).ReadOnly = False?

Я знаю, что в .NET все массивы происходят из System.Array и что класс System.Array реализует IList, ICollection и IEnumerable. Фактические типы массивов также реализуют IList<T>, ICollection<T> и IEnumerable<T>.

Это означает, что если у вас есть, например, String[], то этот объект String[] также является System.Collections.IList и 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!

В обоих случаях попытки удалить элементы с помощью методов Remove() и RemoveAt() приводят к исключению NotSupportedException. Это предполагает, что оба выражения соответствуют спискам ReadOnly, но свойство IList ReadOnly не возвращает ожидаемое значение.

Как получилось?

4b9b3361

Ответ 1

От MSDN:

Массив реализует свойство IsReadOnly, поскольку он требуется Интерфейс System.Collections.IList. Массив, который доступен только для чтения, не допускать добавления, удаления или изменения элементов после массив создается.

Если вам нужна коллекция только для чтения, используйте класс System.Collections который реализует интерфейс System.Collections.IList.

Если вы передаете или преобразуете массив в объект интерфейса IList, Свойство IList.IsReadOnly возвращает false. Однако, если вы бросаете или преобразовать массив в IList <T> интерфейс, свойство IsReadOnly возвращает true.

Только для чтения означает, что элементы в массиве не могут быть изменены и почему он возвращает false.

Также посмотрите Array.IsReadOnly, несовместимый в зависимости от реализации интерфейса.

Ответ 2

Это выглядит как простая ошибка:

  • Он явно не доступен для чтения, поскольку индексщик позволяет его изменять.
  • Он не выполняет преобразование в любой другой объект

Обратите внимание, что вам не нужно бросать - есть неявное преобразование:

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 (который IList<T> наследует свойство from) документирован как:

Коллекция, которая доступна только для чтения, не позволяет добавлять, удалять или изменять элементы после создания коллекции.

В то время как массив не позволяет добавлять или удалять элементы, он явно разрешает модификацию.