L'idée des interfaces est généralement d'exposer une sorte de contrat de base par lequel le code qui effectue un travail sur un objet peut être garanti de certaines fonctionnalités fournies par cet objet. Dans le cas des IEnumerable<T>
Il se trouve que ce contrat est "vous pouvez accéder à tous mes éléments un par un".
Les types de méthodes qui peuvent être écrites sur la base de ce seul contrat sont nombreux. Voir le Enumerable
classe pour tonnes d'exemples.
Mais pour ne retenir qu'un seul exemple concret : pensez à Sum
. De quoi avez-vous besoin pour résumer un ensemble d'éléments ? De quel contrat auriez-vous besoin ? La réponse est très simple : un moyen de voir chaque élément, pas plus. L'accès aléatoire n'est pas nécessaire. Même un décompte total de tous les éléments n'est pas nécessaire.
Pour avoir ajouté un indexeur au IEnumerable<T>
aurait été préjudiciable à deux égards :
- Code qui requiert le contrat décrit ci-dessus (accès à une séquence d'éléments), s'il a requis le code
IEnumerable<T>
serait artificiellement restrictif car il ne pourrait pas traiter un type qui n'implémente pas d'indexeur, même si le traitement d'un tel type devrait être largement dans les capacités du code.
- Tout type qui souhaite exposer une séquence d'éléments mais qui n'est pas équipé de manière appropriée pour fournir un accès aléatoire par index (par ex,
LinkedList<T>
, Dictionary<TKey, TValue>
) devrait maintenant soit fournir des moyens inefficaces de simulant ou encore d'abandonner l'indexation IEnumerable<T>
l'interface.
Ceci étant dit, si l'on considère que l'objectif d'une interface est de fournir une garantie de l'intégrité de l'information. fonctionnalité minimale requise dans un scénario donné, je pense vraiment que les IList<T>
est mal conçue. Ou plutôt, l'absence de une interface "entre" IEnumerable<T>
y IList<T>
(accès aléatoire, mais pas de modification) est, à mon avis, un oubli regrettable dans la BCL.