Как стать автором
Обновить

Комментарии 8

От себя хочу добавить, что до версии 4.5 уже был собственно класс ReadOnlyCollection, но я толком о нём ещё ничего не знаю)))
Лично я побаиваюсь иногда использовать даже FirstOrDefault() ставя его всегда только в конце LINQ-цепочки методов, а посередине спокойнее поставить Take(1) (да, звучит как быдлокод, но на пустой коллекции код выполняется мгновенно, а вот на нулевой ссылке — вываливается исключение)
Ну, FirstOrDefault в середине цепочки для ссылочного типа — это почти гарантированный NullReferenceException. Если уверены, что элемент в коллекции всегда есть — нужно использовать просто First, чтобы это задекларировать.
LSP в определении Роберт С. Мартина:
Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа не зная об этом.

Так что ни о каком нарушении LSP интерфейсом речи быть не может. Проблема не в IEnumerable, а в реализации ToArray, расчитывающей на конечность коллекции. ИМХО, автор тут перекладывает с больной головы на здоровую — IEnumerable нигде конечность коллекции не декларирует.
Именно. IEnumerable предполагает только то, что по коллекции можно пройтись, ничего более.
И кстати это одна из причин не использовать IEnumerable на практике: интерфейс не налагает почти никаких предусловий, что приводит к тому, что реализации интерфейса гарантируемо нарушают принцип LSP, т.к. невозможно реализовать его, не усилив предусловия: требуется либо коннект к базе (в случае с LINQ-2-SQL), либо конечность коллекции (во всех остальных случаях).
Лично я использую и всем рекомендую использовать IList<>, либо IReadOnlyList<>
«В своём предыдущем посте я говорил о конфликте между IQueryable и LSP, но даже ограничивая дискуссию рамками LINQ to Objects, выясняется, что LINQ содержит множество встроенных нарушений LSP.
Вспомним смысл LSP: вы должны иметь возможность передать любую реализацию интерфейса клиенту без изменения корректности системы. В то время как «корректность» является специфичной для приложения, наименьшим общим кратным должно являться то, что если метод работает корректно для одной реализации интерфейса, то он не должен выбрасывать исключения для другой. Впрочем, рассмотрим две реализации IEnumerable:»

С тем же успехом мы можем написать такую структуру:

class A {}
class B: A
{
public B()
{
throw new Exception()
}
}

и говорить, что видите ли наследование нарушает LSP. Мы же не можем подставить B вместо A!

А может дело не в нем, а в том, как мы используем? LINQ ничего не нарушает, если вы хотите сделать бесконечный массив, он попробует его для вас сделать и выпадет и исключением. Как говорится «Машина дура, что ей скажешь, то она и сделает». А если я буду писать код и не буду уверен, что он в точности будет исполняться, то…
Интересно, каким образом IReadOnlyCollection решает проблему с генераторами (бесконечными итераторами)?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории