Pourquoi IList ne prend pas en charge AddRange

89

List.AddRange()existe, mais IList.AddRange()pas.
Cela me paraît étrange. Quelle est la raison derrière cela?

Boris Callens
la source

Réponses:

68

Parce qu'une interface doit être facile à mettre en œuvre et ne pas contenir «tout sauf la cuisine». Si vous ajoutez, AddRangevous devez alors ajouter InsertRangeet RemoveRange(pour la symétrie). Une meilleure question serait de savoir pourquoi il n'y a pas de méthodes d'extension pour l' IList<T>interface similaires à l' IEnumerable<T>interface. (méthodes d'extension pour en place Sort, BinarySearch... serait utile)

xanatos
la source
35
@ShdNx Ils ne sont pas très simples à mettre en œuvre en termes de performances. Un «interne» AddRange/RemoveRange/InsertRangepeut travailler directement sur la collecte «interne» et optimiser la Capacitygestion et utiliser des méthodes comme Array.Copyle déplacement de blocs de données. Une méthode d'extension RemoveRangeserait probablement un ordre de grandeur plus lent queList.RemoveRange
xanatos
2
C'est dommage qu'il n'y ait pas (et n'est toujours pas) de moyen pour une IFoodéclaration d' interface (par exemple ) de spécifier un espace de noms "helper" (par exemple MyAssembly) de telle sorte que si une classe prétend implémenter IFoomais manque de méthode int Bar(String), le compilateur serait automatiquement generate method int IFoo.Bar(String p1) {return MyAssembly.ClassHelpers.IFoo.Bar(this, p1);} Si une telle fonctionnalité avait existé, les interfaces auraient pu inclure plus de méthodes comme celles AddRangequi pourraient être implémentées en termes de comportement de base, mais que certaines implémentations pourraient optimiser.
supercat du
1
Ils pourraient être implémentés en tant que méthodes d'extension, de cette façon l'implémentation de l'interface n'aurait pas à les implémenter. Pourquoi pas?
Tom Pažourek
15
Cela n'a aucun sens. Une interface fait abstraction d'une implémentation, de sorte qu'il puisse y avoir plusieurs implémentations des mêmes fonctionnalités de base; il n'y a aucune raison pour que les fonctionnalités soient omises d'une interface, car "l'implémentation est difficile". Sans méthodes comme "AddRange" sur l'interface, il n'y a aucune garantie que l'objet sous-jacent les prend en charge, et à ce stade, vous êtes obligé d'implémenter une extension sous-optimale ou de contourner le but d'utiliser une interface en faisant des hypothèses dangereuses en essayant de cast vers une classe d'implémentation spécifique. Les interfaces simplifiées sont surutilisées.
Triynko le
3
L'interface IRangeList devrait prendre en charge les opérations en masse, implémentée uniquement sur certaines collections dont l'implémentation en interne sera optimale.
trop
8

Pour ceux qui veulent avoir des méthodes d'extension pour "AddRange", "Sort", ... sur IList,

Voici la AddRangeméthode d'extension:

 public static void AddRange<T>(this IList<T> source, IEnumerable<T> newList)
 {
     if (source == null)
     {
        throw new ArgumentNullException(nameof(source));
     }

     if (newList == null)
     {
        throw new ArgumentNullException(nameof(newList));
     }

     if (source is List<T> concreteList)
     {
        concreteList.AddRange(newList);
        return;
     }

     foreach (var element in newList)
     {
        source.Add(element);
     }
}

J'ai créé une petite bibliothèque qui fait cela. Je trouve cela plus pratique que de devoir refaire ses méthodes d'extension sur chaque projet.

Certaines méthodes sont plus lentes que List, mais elles font le travail.

Voici le GitHub pour les intéresser:

Dépôt IListExtension

Emilien Mathieu
la source