Использование IReadOnlyCollection<T>
или IReadOnlyList<T>
в сигнатуре метода вместо IEnumerable<T>
, имеет то преимущество, что делает явным то, что вам может потребоваться проверить счетчик перед итерацией или выполнить итерацию несколько раз по какой-либо другой причине.
Однако у них есть огромный недостаток, который вызовет проблемы, если вы попытаетесь изменить код для использования интерфейсов, например, чтобы сделать его более тестируемым и дружественным для динамического прокси. Ключевым моментом является то, что IList<T>
он не наследуетсяIReadOnlyList<T>
и аналогично для других коллекций и их соответствующих интерфейсов только для чтения. (Короче говоря, это потому, что .NET 4.5 хотел сохранить совместимость ABI с более ранними версиями. Но они даже не воспользовались возможностью изменить это в ядре .NET. )
Это означает, что если вы получили какой- IList<T>
то фрагмент программы и хотите передать его в другую часть, которая ожидает IReadOnlyList<T>
, вы не сможете! Вы можете однако передать IList<T>
какIEnumerable<T>
.
В конце концов, IEnumerable<T>
это единственный интерфейс только для чтения, поддерживаемый всеми коллекциями .NET, включая все интерфейсы коллекций. Любая другая альтернатива вернется, чтобы укусить вас, когда вы поймете, что вы отстранены от некоторых архитектурных решений. Поэтому я думаю, что это правильный тип для использования в сигнатурах функций, чтобы выразить, что вы просто хотите коллекцию только для чтения.
(Обратите внимание, что вы всегда можете написать IReadOnlyList<T> ToReadOnly<T>(this IList<T> list)
метод расширения, который будет просто приводить , если базовый тип поддерживает оба интерфейса, но вы должны добавлять его вручную везде при рефакторинге, где IEnumerable<T>
это всегда совместимо.)
Как всегда, это не является абсолютным, если вы пишете код, насыщенный базой данных, где случайное множественное перечисление может привести к катастрофе, вы можете предпочесть другой компромисс.