L'utilisation de IReadOnlyCollection<T>
ou IReadOnlyList<T>
dans la signature de méthode au lieu de IEnumerable<T>
, a l'avantage de rendre explicite le fait que vous devrez peut-être vérifier le nombre avant l'itération ou répéter plusieurs fois pour une autre raison.
Cependant, ils ont un énorme inconvénient qui causera des problèmes si vous essayez de refactoriser votre code pour utiliser des interfaces, par exemple pour le rendre plus testable et plus convivial pour le proxy dynamique. Le point clé est qu'il IList<T>
n'hérite pasIReadOnlyList<T>
et de la même manière pour les autres collections et leurs interfaces en lecture seule respectives. (En bref, cela est dû au fait que .NET 4.5 voulait conserver la compatibilité ABI avec les versions antérieures. Mais ils n'ont même pas profité de l'occasion pour changer cela dans .NET core. )
Cela signifie que si vous obtenez un IList<T>
d'une partie du programme et que vous souhaitez le passer à une autre partie qui attend un IReadOnlyList<T>
, vous ne pouvez pas! Vous pouvez cependant passer un IList<T>
comme unIEnumerable<T>
.
Au final, IEnumerable<T>
c'est la seule interface en lecture seule prise en charge par toutes les collections .NET, y compris toutes les interfaces de collection. Toute autre alternative reviendra vous mordre lorsque vous réaliserez que vous vous êtes exclu de certains choix d'architecture. Je pense donc que c'est le type approprié à utiliser dans les signatures de fonction pour exprimer que vous voulez juste une collection en lecture seule.
(Notez que vous pouvez toujours écrire une IReadOnlyList<T> ToReadOnly<T>(this IList<T> list)
méthode d'extension qui effectue une conversion simple si le type sous-jacent prend en charge les deux interfaces, mais vous devez l'ajouter manuellement partout lors de la refactorisation, où as IEnumerable<T>
est toujours compatible.)
Comme toujours, ce n'est pas un absolu, si vous écrivez du code lourd de base de données où une énumération multiple accidentelle serait un désastre, vous préférerez peut-être un compromis différent.