Почему я могу передать массив методу, принимающему 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, которое немного смягчает ситуацию; хотя дизайн мне все равно не нравится).