Я думаю, что на самом деле есть два вопроса, чтобы ответить здесь.
Когда бы я хотел IEnumerable<T>
?
В отличие от других типов коллекций и языка в целом запросы на IEnumerable
s выполняются с ленивой оценкой.Это означает, что вы можете выполнить несколько связанных запросов только в перечислении.
Стоит отметить, что ленивая оценка не очень хорошо взаимодействует с побочными эффектами, потому что многократное перечисление может дать разные результаты, вы должны помнить об этом при использовании. На языке, подобном C#, ленивая оценка может быть очень мощным инструментом, но также источником необъяснимого поведения, если вы не будете осторожны.
Когда я не хочу ICollection<T>
?
ICollection<T>
- это изменяемый интерфейс, он предоставляет, среди прочего, добавлять и удалять методы. Если вы не хотите, чтобы внешние вещи изменяли содержимое вашего объекта, вы не хотите его возвращать. Аналогично, вы, как правило, не хотите передавать его в качестве аргумента по той же причине.
Если вам нужна явная изменчивость коллекции, обязательно используйте ICollection<T>
.
Кроме того, в отличие от IEnumerable<T>
или IReadOnlyCollection<T>
, ICollection<T>
не является ковариантным, что снижает гибкость типа в определенных случаях использования.
Non-дженерики
Вещи немного изменить, когда речь идет о необщего версии этих интерфейсов. В этом случае единственной реальной разницей между ними является ленивая оценка, предлагаемая IEnumerable
, и плавная оценка ICollection
.
Я лично хотел бы избежать необоснованных версий из-за отсутствия безопасности типов и низкой производительности при боксировании/распаковке в случае типов значений.
Резюме
Если вы хотите ленивые вычисления, используйте IEnumerable<T>
. Для нетерпеливой оценки и неизменности используйте IReadOnlyCollection<T>
. Для использования явной изменчивости ICollection<T>.
'IEnumerable' - родительский интерфейс' ICollection'. Поэтому, если ваш метод принимает только ICollection ', он не может быть повторно использован, как если бы он принял' IEnumerable '. Также обратите внимание, что многие методы расширения LINQ пытаются использовать для 'IList' или' ICollection' для использования свойства вместо перечисления последовательности. 'Enumerable.Count' оптимизирован, поскольку вы можете видеть [здесь] (http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,41ef9e39e54d0d0b.references). –
@TimSchmelter: thanks Tim. Утверждение ** Итак, если вы говорите, что ваш метод принимает только ICollection, он не может быть повторно использован, как если бы вы принимали IEnumerable ** однако отвечает «почему бы не использовать A вместо B, если A есть B +». Если по каким-либо причинам IEnumerable более широко используется, все же не является причиной того, что нельзя использовать ICollection, поскольку ICollection является IEnumerable (если только это не так). –
Veverke
@Veverke, если нет конкретной причины не делать этого, вы всегда должны предпочитать более высокий класс в иерархии, который имеет все, что вам нужно. Это дает большую гибкость: если в «ICollection» нет ничего конкретного, использование «IEnumerable» дает большую гибкость. – Jcl