Предложения ToArray
и ToList
раскрывают нечто большее, чем можно было бы изначально представить.Мы склонны думать, что этот совет просто говорит, что вызов ToList
/ ToArray
либо на сайте вызова, либо в первую очередь в вашем методе исправляет проблему, но ваш вопрос в том, подходит ли IEnumerable<T>
- выможет измениться с типа параметра с IEnumerable<T>
на что-то другое (например, ICollection<T>
), что возлагает ответственность на вызывающего, чтобы преобразовать во что-то, реализующее этот интерфейс (обратите внимание, что T[]
, List<T>
, IList<T>
и Collection<T>
все делают).Часть проблемы с этим подходом состоит в том, что эти интерфейсы представляют изменяемые коллекции, тогда как IEnumerable<T>
объявляет, что метод перечисляет элементы - только одна из причин, почему мне не нравится этот подход.
Что если потенциальная ошибкана самом деле не было ошибки?Возможно, вызывающий объект хочет, чтобы это были защитные копии или объекты с тупыми данными - в этих последних случаях это может быть неэффективно в некоторой мере, но он требует от них сделать копию - но в этом предлагаемом использовании это определенно не ошибка.Точно так же, один размер подходит всем рекомендациям, не подходит, потому что IEnumerable<T>
объекты не должны когда-либо заканчиваться - но требование передачи типа массива будет означать, что бесконечный (то есть вычисляемый) или просто большой IEnumerable<T>
об объектах не может быть и речи.
Несмотря на это, я думаю, что вы правы, задавая вопросы, касающиеся защитного программирования.Однако в этом случае я думаю, что лучшим решением будет придерживаться IEnumerable<T>
и обучать, а не ограничивать своих абонентов, основываясь на предположении, что они могут, в некоторых ограниченных обстоятельствах, ввести ошибку.
Перефразируя цитату:
Проблема с проектированием для предотвращения проблем, которые будут создавать идиоты, заключается в том, что идиоты настолько чертовски гениальны.
Надеюсь, это поможет.Ура!