O uso IReadOnlyCollection<T>
ou IReadOnlyList<T>
na assinatura do método, em vez de IEnumerable<T>
, tem a vantagem de tornar explícito que você pode precisar verificar a contagem antes de iterar ou iterar várias vezes por algum outro motivo.
No entanto, eles têm uma enorme desvantagem que causará problemas se você tentar refatorar seu código para usar interfaces, por exemplo, para torná-lo mais testável e amigável ao proxy dinâmico. O ponto principal é que IList<T>
não herda deIReadOnlyList<T>
e da mesma forma para outras coleções e suas respectivas interfaces somente leitura. (Em resumo, isso ocorre porque o .NET 4.5 queria manter a compatibilidade ABI com versões anteriores. Mas eles nem aproveitaram a oportunidade para mudar isso no núcleo do .NET. )
Isso significa que, se você obtém uma IList<T>
parte de algum programa e deseja passá-lo para outra parte que espera uma IReadOnlyList<T>
, não pode! No entanto, você pode passar um IList<T>
como umIEnumerable<T>
.
No final, IEnumerable<T>
é a única interface somente leitura suportada por todas as coleções .NET, incluindo todas as interfaces de coleção. Qualquer outra alternativa voltará a mordê-lo quando você perceber que se excluiu de algumas opções de arquitetura. Então eu acho que é o tipo apropriado para usar em assinaturas de funções para expressar que você deseja apenas uma coleção somente leitura.
(Observe que você sempre pode escrever um IReadOnlyList<T> ToReadOnly<T>(this IList<T> list)
método de extensão que faça a conversão simples, se o tipo subjacente suportar as duas interfaces, mas você deve adicioná-lo manualmente em qualquer lugar ao refatorar, onde IEnumerable<T>
sempre é compatível.)
Como sempre, isso não é absoluto; se você estiver escrevendo um código pesado para o banco de dados, em que a enumeração múltipla acidental seria um desastre, talvez prefira uma troca diferente.