Почему я могу передать массив методу, принимающему IList, что приводит к ошибке при попытке использовать этот интерфейс (массив, очевидно, не поддерживает Add())
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string[] thisIsArray = ["A", "B"];
IsThisBug(thisIsArray);
}
public static void IsThisBug(IList<string> array) {
array.Add("Hello");
}
}
Часто бывает полезно поддерживать такой интерфейс, даже если не каждый метод может быть полностью реализован; например, в отличие от более строгого ICollection
, IList
также добавляет индексатор this[int index] {get;set;}
, который может поддерживать массив - поэтому, если бы массив реализовал только ICollection
, некоторые другие полезные функции были бы потеряны. У него также есть свойство .IsFixedSize
, которое вам следует проверить, прежде чем пытаться использовать .Add(...)
, поэтому NotSupportedException
не является сюрпризом.
IsFixedSize? Должно быть IsReadOnly. Не должно сильно измениться, но IsFixedSize звучит очень косвенно.
Я думаю, вы имеете в виду использовать IsReadOnly
, а не IsFixedSize
В общем IList<T> нет свойства IsFixedSize. Правильно ли мне использовать IList<T>? IList<строка> x = ["A"]; IList y = (IList)x; if (!y.IsFixedSize) { x.Add("хмм"); } ((извините, не знаю, как разместить здесь фрагмент кода в комментариях...))
@Ralf (отвечая на удаленный комментарий) нет, IList<T>
не реализует IList
; многие типы, реализующие IList<T>
, также реализуют IList
, но это не совсем одно и то же утверждение; и да, в этом случае есть небольшой пробел в обнаружении
@Demo для форматирования кода в комментариях: ` обратные кавычки - т. е. `foo` — это foo
Мне потребовалась секунда, чтобы осознать это, но твои навыки чтения гораздо быстрее.
@Demo: На самом деле это неуниверсальный интерфейс IList
, обладающий свойством IsFixedSize
. Общий ICollection<T>.IsReadOnly
возвращает true
для массива, указывая, что ICollection<T>.Add
/Remove
/Clear
не поддерживаются. И да, это очень сбивает с толку, что необобщенный IList
вместо этого имеет комбинацию IsReadOnly
/IsFixedSize
, возвращая false
/true
для массива, указывая, что IList.this[]
поддерживается, а другие мутирующие члены - нет.
Я не знаю readOnly
, это тоже сбивает с толку. Я бы не ожидал, что что-то readOnly будет изменчивым (как массив). dotnetfiddle.net/f4jBl1 и иметь разное значение для массива (изменяемого, но фиксированного размера), неизменяемого списка (не изменяемого). Мои выводы из этого: А) это предполагаемое поведение, Б) Добавление в IList<> сложнее, чем я знал
Array
действительно реализует IList
, за исключением того, что он специально генерирует исключение для Add
, которое вы можете увидеть в исходном коде
Одно из наиболее вопиющих нарушений принципа замены Лискова со стороны Microsoft (по крайней мере, технически — есть свойство
IsReadOnly
, которое немного смягчает ситуацию; хотя дизайн мне все равно не нравится).