Voir la définition de la classe System.Array
public abstract class Array : IList, ...
Théoriquement, je devrais pouvoir écrire ce morceau et être heureux
int[] list = new int[] {};
IList iList = (IList)list;
Je devrais également pouvoir appeler n'importe quelle méthode à partir de l'iList
ilist.Add(1); //exception here
Ma question n'est pas pourquoi j'obtiens une exception, mais plutôt pourquoi Array implémente IList?
Parce qu'un tableau permet un accès rapide par index et IList
/IList<T>
is sont les seules interfaces de collecte qui prennent en charge cela. Alors peut-être que votre vraie question est "Pourquoi n'y a-t-il pas d'interface pour les collections constantes avec des indexeurs?" Et à cela je n'ai pas de réponse.
Il n'y a pas non plus d'interface en lecture seule pour les collections. Et je les manque encore plus qu'une interface de taille constante avec indexeurs.
OMI, il devrait y avoir plusieurs interfaces de collecte (génériques) supplémentaires selon les caractéristiques d'une collection. Et les noms auraient dû être différents aussi, List
pour quelque chose avec un indexeur est vraiment stupide IMO.
IEnumerable<T>
ICollection<T>
IList<T>
Je pense que les interfaces de collection actuelles sont de mauvaise conception. Mais comme ils ont des propriétés vous indiquant quelles méthodes sont valides (et cela fait partie du contrat de ces méthodes), cela ne rompt pas le principe de substitution.
La section des remarques de documentation pour IList
dit
IList est un descendant de l'interface ICollection et est l'interface de base de toutes les listes non génériques. Les implémentations IList se répartissent en trois catégories: lecture seule, taille fixe et taille variable . Un IList en lecture seule ne peut pas être modifié. Une IList de taille fixe ne permet pas l'ajout ou la suppression d'éléments, mais elle permet la modification d'éléments existants. Une IList de taille variable permet l'ajout, la suppression et la modification d'éléments.
De toute évidence, les tableaux entrent dans la catégorie de taille fixe, donc par la définition de l'interface, cela a du sens.
Parce que tous les IList
ne sont pas mutables (voir IList.IsFixedSize
et IList.IsReadOnly
), et les tableaux se comportent certainement comme des listes de taille fixe.
Si votre question est vraiment "pourquoi implémente-t-elle une interface non générique ", alors la réponse est que celles-ci existaient avant l'arrivée des génériques.
C'est un héritage que nous avons depuis l'époque où il n'était pas clair comment gérer les collections en lecture seule et si Array est en lecture seule ou non. Il existe des indicateurs IsFixedSize et IsReadOnly dans l'interface IList. L'indicateur IsReadOnly signifie que la collection ne peut pas être modifiée du tout et IsFixedSize signifie que la collection autorise la modification, mais pas l'ajout ou la suppression d'éléments.
Au moment de .Net 4.5, il était clair que certaines interfaces "intermédiaires" sont nécessaires pour fonctionner avec des collections en lecture seule, donc IReadOnlyCollection<T>
et IReadOnlyList<T>
ont été introduits.
Voici un excellent article de blog décrivant les détails: Lire uniquement les collections dans .NET
La définition de l'interface IList est "Représente une collection non générique d'objets accessibles individuellement par index". Array satisfait complètement cette définition, doit donc implémenter l'interface. L'exception lors de l'appel de la méthode Add () est "System.NotSupportedException: la collection était d'une taille fixe" et s'est produite parce que le tableau ne peut pas augmenter sa capacité dynamiquement. Sa capacité est définie lors de la création d'un objet tableau.