Pull to refresh

Comments 13

Сначала вы берёте List как эталонную реализацию и говорите, что Reset, Current и MoveNext могут бросать исключения когда им вздумается:
единственное, в чем мы можем быть уверены при работе с IEnumerable, это то, что метод IEnumerable.GetEnumerator() возвращает ненулевой (non-null) объект энумератора
А потом запрещаете другой реализации кидать исключения:
Такая имплементация нарушает LSP, т.к. интерфейс IEnumerable сам по себе не имеет никаких предусловий, требующих наличия открытого подключения к базе данных.
Здесь либо и то, и другое нарушают LSP, потому что накладывают дополнительные ограничения на вызовы методов, либо ничто не нарушает.
метод Process ожидает от объекта, реализующего IEnumerable, большего, чем этот интерфейс обещает
Вовсе нет. Нигде не объявлено, что Process работает с конечной коллекцией. Бесконечно обрабатывать запросы — вполне валидная задача.
Сначала вы берёте List как эталонную реализацию и говорите, что Reset, Current и MoveNext могут бросать исключения когда им вздумается:

Нет, я как раз пишу, что Reset и Current могут бросать исключения как им вздумается (исходя из нескольких реализаций в .NET), а вот MoveNext всегда возвращает bool, и не имеет при этом никаких предусловий. DbQuery нарушает принцип, потому что усиливает предусловия именно в MoveNext, а не в Reset или Current. Думаю стоило обозначить это более явно.

Вовсе нет. Нигде не объявлено, что Process работает с конечной коллекцией. Бесконечно обрабатывать запросы — вполне валидная задача.

Тут тоже наверное нужно было подобрать более подходящий пример. Этим примером я хотел показать, что Process ожидает именно конечную коллекцию. То, что бесконечная обработка запросов является валидной задачей — это безусловно.
MoveNext всегда возвращает bool, и не имеет при этом никаких предусловий
Ещё как имеет.

IEnumerable<int> list = new List<int> { 1 };
IEnumerator<int> etor = list.GetEnumerator();
((List<int>)list).Add(2);
etor.MoveNext(); // exception
Да, этот момент я пропустил. Согласен, предусловия у MoveNext есть, но все же они не требуют наличия коннекта к БД (если за эталон брать реализацию List-а и пары других реализаций в BCL). Тут опять же вопрос — что брать за эталон, т.к. явных контрактов эти интерфейсы не объявляют.
Я, честно говоря, по названию полагал, что будут обсуждаться библиотечные реализации IEnumerable, которые нарушают LSP, а автор обсуждает вместо этого 3 кастомные реализации, причем две из них абсолютно валидны с точки зрения LSP, а третья (связанная с базой данных), откровенно некорректная, но не из-за Принципа Подстановки Лисков, а потому что не выполняет того для чего она сделана (не возвращает последовательность строк из бд) вследствие ошибки реализации.
а потому что не выполняет того для чего она сделана
Ну почему, реализация обещает вернуть нечто итерируемое, а не проитерированное, контракт соблюдён. Готовая последовательность строк из бд — это про IReadOnlyCollection(Of T)/IReadOnlyList(Of T)
Реализация обещает итерируемое, но при попытке его проитерировать — бросает всегда исключение. Это явно не то поведение, которое закладывал разработчик. Так зачем обсуждать эту реализацию? В правильной реализации будет создаваться дб контекст при получении экземпляра итератора, и диспозится при вызове метода Dispose() итератора.
Свойство Current с типом T не требует вызова MoveNext(), в то время как свойство Current с типом object требует:
Что, кстати, по идее, ошибка реализации:
After an enumerator is created or after the Reset method is called, the MoveNext method must be called to advance the enumerator to the first element of the collection before reading the value of the Current property; otherwise, Current is undefined.
MSDN
>> public int GetTheTenthElement(IEnumerable collection)
>> public int GetTheTenthElement(IReadOnlyList collection)
я завидую, с какой легкостью ужесточается интерфейс метода
Разве Skip и Take 10 раз итерируют перечиление? Один обход там только будет, насколько я помню («Не смотря на то, что такой код довольно прост, он имеет один очевидных недостаток: в нем происходит итерирование коллекции 10 раз»)
Он имеет ввиду, что там будет сделано 10 раз MoveNext, тогда как если брать по индексу — одна операция.
Sign up to leave a comment.

Articles