web-dev-qa-db-fra.com

Pourquoi le tableau implémente IList?

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?

133
oleksii

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.

  • Énumération juste IEnumerable<T>
  • Lecture seule mais pas d'indexeur (.Count, .Contains, ...)
  • Redimensionnable mais sans indexeur, c'est-à-dire défini comme (Ajouter, Supprimer, ...) actuel ICollection<T>
  • Lecture seule avec indexeur (indexeur, index de, ...)
  • Taille constante avec indexeur (indexeur avec setter)
  • Taille variable avec indexeur (Insert, ...) current 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.

89
CodesInChaos

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.

39
Brian Rasmussen

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.

17
Mehrdad

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

4
Vladimir

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.

0
meir