Какой тип универсальной коллекции в каком случае использовать?

1,00
р.
Пространство имен System.Collection.Generic содержит несколько интерфейсов для работы с универсальными коллекциями.
Наиболее часто мне попадаются следующие интерфейсы:
IEnumerable ICollection IList
Хотелось бы узнать, в каких случая рекомендуется использовать тот или иной тип, какие плюсы и минусы использования их по соотношению к друг другу.

Ответ
Это семантически разные коллекции, каждая из них добавляет более строгие ограничения, но дает новые возможности:
IEnumerable - это, строго говоря, не коллекция. Это просто последовательность, которую можно перебрать по одному элементу. Нельзя, например, рассчитывать на то, что
ее можно перебрать дважды ее вообще можно перебрать до конца
ICollection - это полноценная коллекция. У нее есть конечное количество элементов, элементы в нее можно добавлять. Имея элемент, можно проверить на существование его в коллекции. И, естественно, коллекцию можно очистить.
IList - это коллекция, элементы в которой пронумерованы.
Соответственно, применять нужно то, что позволяют ограничения в каждом конкретном случае. Например:
Последовательность Фибоначчи - это IEnumerable - ее можно перебрать. Но это не ICollection - в ней нельзя пересчитать элементы, и в нее нельзя добавить новый элемент. И ее точно нельзя "очистить" :) Множество - HashSet - это ICollection, количество элементов в нем известно, можно добавить новый элемент, можно проверить на существование элемента. Но элементы в множестве никак не отсортированы и не пронумерованы. Соответственно, это не List. Аналогично - Dictionary - ICollection<>, но не IList<>
Решение "что использовать" обычно принимается в двух случаях:
При реализации собственной коллекции - и тогда стоит просто выбирать тот интерфейс, под ограничения которого ваша коллекция попадает. При возврате значения их свойства или метода. Например, внутри у вас есть List. Возвращать ли его как IList, или как IEnumerable - опять же, зависит от контекста. Если подразумевается возврат именно коллекции, но ваш класс не должен реагировать на ее модификацию - то можно вернуть IReadOnlyCollection. Если вызывающему достаточно последовательности - ограничьтесь IEnumerable. Возвращать внутренний List или T[], в зависимости от контекста, может быть небезопасно - вызывающий код сможет напрямую поменять внутренний список вашего класса и поломать вам всю инкапсуляцию.
Сама по себе тема подробно раскрыта в официальном Framework Design Guidelines - Guidelines for Collections.