Array
класс реализует IList
интерфейс, который имеет Add
член. Array.Add
вызов выдает NotSupportedException
. Является ли это нарушением принципа замещения Лисков или принципа разделения интерфейса или обоих?
Нарушает ли метод Array.Add LSP?
Ответы (2)
Это определенно нарушение принципа разделения интерфейса. Интернет-провайдер утверждает, что компоненты должны зависеть только от тех интерфейсов, которые им действительно требуются. Array
реализует IList
, но явно не нуждается во всех методах, определенных IList
, потому что он выбирает исключение, объясняющее, что он не поддерживает Add
. Кроме того, все, что нуждается в Array
, теперь имеет IList
, несмотря на то, что не нуждается во всех его методах (потому что все, что требует массив, явно не беспокоится о Add
, так как он все равно не работает). Отсутствие поддержки операции, которую ваш интерфейс предлагает вам реализовать, явно является нарушением интернет-провайдера; принуждение потребляющего кода к зависимости от интерфейса, несмотря на то, что он не нужен полностью, также является нарушением ISP.
Это может привести к нарушению принципа подстановки Лискова. Если код зависит от IList
, LSP заявляет, что он должен работать правильно при передаче любой реализации IList
. Однако при передаче Array
этот код теперь будет генерировать исключение каждый раз, когда он попытается вызвать Add
.
Является ли это нарушением LSP, зависит от того, как вы видите исключения в отношении LSP. Если подойти к этому с точки зрения того, что исключения являются частью ожидаемого контракта, то все в порядке. Метод соответствует своему контракту, и любой код, который вызывает Add
без учета возможности исключения, виноват в том, что этого не происходит.
Если вы больше придерживаетесь мнения, что NotSupportedException
считается ошибкой или сбоем, то это явное нарушение LSP. Лично я считаю, что принципы SOLID поддерживают друг друга и их сложнее решать в вакууме, поэтому, используя принцип сегрегации интерфейса в качестве резервной копии, я бы сказал, что интерфейс говорит: «Я могу делать эти вещи», поэтому говоря: «На самом деле, Я не могу сделать это" является ошибкой, и поэтому, вероятно, не должно рассматриваться как часть действительного контракта. Если исключение не является частью контракта, то, выбрасывая его, Array
нарушает контракт Add
и, следовательно, нарушает LSP.
IList<T>
реализован явно в массивах, поэтому вы не получаете методы по умолчанию, если не выполняете приведение к интерфейсу. В остальном массив действует аналогично неизменяемому списку. Возможно, это компромисс из-за отсутствия интерфейса IReadonlyList
, который просто разрешает индексированный доступ для чтения (хотя массивы также разрешают индексированный доступ для записи), сохраняя при этом приятный язык в использовании.
- person Joey; 29.09.2017
Add
, в чем, если я правильно понял, и заключается LSP.
- person Stefan; 29.09.2017
.Add()
, что фактически означает, что любой метод, который вызывает .Add()
через IList
, является несчастным случаем, ожидающим своего часа. Таким образом, передача массива методу, который принимает IList()
, который явно не документирует, что он не вызывает .Add()
, будет неправильным — вот почему такое нарушение — это так плохо.
- person Matthew Watson; 29.09.2017
list.IsReadOnly
, чтобы определить, не может ли список вызываться .Add()
, но, к сожалению, это list.IsReadOnly
ложно для типов массивов. Если вы вызовете следующий метод и передадите ему массив, он вернет false: public static bool IsreadOnly(IList list) { return list.IsReadOnly; }
- person Matthew Watson; 29.09.2017
Принцип подстановки Лисков –
Программу, использующую интерфейс, не следует путать с реализацией этого интерфейса.
Массивы составляют исключение в случае реализации IList‹› — что запутано.
void Main()
{
var arr = new int[]{1,2,3};
Test(arr);
void Test(IList<int> list)
{
list.Add(4);
}
}
ICollection
и получаетArray
, он, похоже, терпит неудачу наAdd
(заявлено OP) - person Stefan   schedule 29.09.2017IList.Add
вместоICollection.Add
, в то время какNotSupportedException
является ожидаемым исключениемIList.Add
согласно msdn.microsoft.com/en-us/library/. Я не думаю, что нарушают LSP. - person qxg   schedule 29.09.2017Liskov's notion of a behavioral subtype defines a notion of substitutability for objects; that is, if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g. correctness).
Очевидно, что если вы передадите массив и метод попытается вызвать.Add()
, это нарушит корректность программы. Документирование исключения не делает его ОК. - person Matthew Watson   schedule 29.09.2017