Использование IReadOnlyCollection <T> вместо IEnumerable <T> для параметров, чтобы избежать возможного множественного перечисления

Мой вопрос связан с этим вопросом об использовании IEnumerable<T> vs IReadOnlyCollection<T>.

Я также всегда использовал IEnumerable<T> чтобы выставлять коллекции как возвращаемые типы и параметры, так как он выигрывает от неизменности и ленивости.

Тем не менее, меня все больше беспокоит распространение мест в моем коде, где я должен перечислить параметр, чтобы избежать возможного предупреждения о множественном перечислении, которое дает ReSharper. Я понимаю, почему ReSharper предлагает это, и я согласен с кодом, который он предлагает (ниже), чтобы обеспечить инкапсуляцию (т.е. Никаких предположений о вызывающем абоненте).

 Foo[] arr = col as Foo[] ?? col.ToArray();

Тем не менее, я нахожу повторяемость этого кода загрязняющим, и я согласен с некоторыми источниками в том, что IReadOnlyCollection<T> - лучшая альтернатива, особенно точки, сделанные в этой статье, в которой говорится:

В последнее время я рассматривал достоинства и недостатки возврата IEnumerable<T>.

С положительной стороны он примерно такой же минимальный, как и интерфейс, поэтому он оставляет вас в качестве автора метода большей гибкостью, чем перенос на более тяжелую альтернативу, такую как IList<T> или (не дай бог) массив.

Однако, как я изложил в последнем сообщении, возврат IEnumerable<T> побуждает вызывающих абонентов нарушать Принцип замещения Лискова. Слишком просто для них использовать методы расширения LINQ, такие как Last() и Count(), чья семантика IEnumerable<T> не обещает.

Что нужно, это лучший способ заблокировать возвращенную коллекцию, не делая таких соблазнов столь выдающимися. (Мне вспоминается, что Барни Файф усвоил этот урок).

Введите IReadOnlyCollection<T>, новый в.NET 4.5. Он добавляет только одно свойство к IEnumerable<T>: свойство Count. Пообещав подсчет, вы заверяете своих абонентов, что у вашего IEnumerable<T> действительно есть конечная точка. Затем они могут использовать методы расширения LINQ, такие как Last() с чистой совестью.

Однако, как заметил наблюдатель, в этой статье говорится об использовании IReadOnlyCollection<T> для возвращаемых типов. Мой вопрос в том, будут ли одинаковые аргументы одинаково применимы и к его использованию для параметров? Любые теоретические мысли или комментарии по этому вопросу также будут оценены.

На самом деле, я думаю, что общее правило для использования IReadOnlyCollection<T> будет там, где будет возможно множественное перечисление (vis- à -vis предупреждение ReSharper), если используется IEnumerable<T>. В противном случае используйте IEnumerable<T>.

Ответ 1

Подумав об этом дальше, я пришел к выводу, основываясь на статье, упомянутой в моем Вопросе, о том, что действительно полезно использовать IReadOnlyCollection<T> в качестве параметра, но только в тех функциях, где он определенно будет перечисляться, Если перечисление является условным, основанным на других параметрах, состоянии объекта или рабочем процессе, тогда он все равно должен быть передан как IEnumerable<T>, чтобы ленивая оценка была семантически гарантирована.