Мое эмпирическое правило таково:
Если когда-нибудь появится шанс, что я смогу взять основной алгоритм подпрограммы и реорганизовать его так, чтобы я мог использовать возвращаемую доходность, я пойду с IEnumerable .
Например, если моя текущая реализация использует массив или List для внутреннего использования, но я знаю, что, по крайней мере, теоретически, я могу захотеть и иметь возможность переработать его внутренне для выполнения отложенной оценки, я вернусь IEnumerable .
Я обнаружил, что выгоды от возвращения IEnumerable определенно стоят хлопот с его использованием.
Однако, если алгоритму по своей природе потребуется полностью оценить результаты перед возвратом (редко, но это случается), я пойду с IList . В основном, если я уже вычисляю это, я верну это. IList реализует IEnumerable , поэтому все связанные с LINQ варианты использования по-прежнему работают, но вы теряете ленивую оценку. Если я уже вынужден оценивать заранее, это не проблема.
Я редко возвращаю IQueryable. Единственный раз, когда я бы использовал этот интерфейс, это если я непосредственно создаю запрашиваемый слой доступа к данным или что-то подобное. Затраты на его использование в большинстве случаев не стоят выигрыша.
Однако, если ваша цель - всегда использовать один интерфейс (я не обязательно согласен с этой целью), я бы придерживался IEnumerable .