Использование 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>
, чтобы ленивая оценка была семантически гарантирована.