.NET 4.5Deux nouvelles interfaces de collection, IReadOnlyList et IReadOnlyDictionary, ont été ajoutées. Bien que ces interfaces puissent sembler superficielles si banales, elles révèlent des histoires assez complexes sur la rétrocompatibilité, l’interopérabilité et le rôle de la comutabilité.
IReadOnlyList et IReadOnlyDictionary sont deux interfaces que les développeurs .NET ont toujours voulu avoir. En plus de fournir un certain sens de symétrie (par opposition aux interfaces écrivables), une interface en lecture seule doit éliminer l’implémentation de méthodes qui ne font qu’une exception NotSupportedException sans rien faire. Tout cela n’a pas été achevé en raison de contraintes de temps.
La prochaine opportunité est là. NET 2.0. Cela permet à Microsoft de retirer les collections faiblement typées et de les remplacer par des collections pairs fortement typées. Cependant, l’équipe de la bibliothèque de base[1] a de nouveau manqué l’occasion de fournir une liste en lecture seule, comme l’a écrit Kit George,
Puisque nous avons l’intention de fournir une implémentation par défaut pour le problème dont vous parlez avec Joe, plutôt que de fournir une interface, nous fournissons la classe de base ReadOnlyCollectionBase. Cependant, je comprends pourquoi certaines personnes hésitent à l’utiliser car ce n’est pas un type fort. Mais avec l’introduction des génériques, nous avons désormais aussi <T>ReadOnlyCollection, ce qui vous permet non seulement d’avoir la même fonctionnalité, mais aussi un type puissant : super !
Puisque <T>ReadOnlyCollection n’est pas une classe scellée, vous pouvez écrire votre propre collection à pleine vitesse si nécessaire. Parce que ces collections que nous avons créées pour cela sont adaptables aux besoins généraux, nous ne prévoyons pas d’introduire des interfaces pour ce même concept. Krzysztof Cwalina a également exprimé son opinion sur ce sujet,
Que cela puisse paraître surprenant ou non, IList et IList <T>sont les deux interfaces que nous avons l’intention d’utiliser pour les collections en lecture seule. Ils possèdent tous deux la propriété booléenne IsReadOnly, qui devrait être vraie lorsqu’une collection en lecture seule implémente cette propriété. La raison pour laquelle nous ne voulons pas ajouter une interface purement en lecture seule est que nous pensons que cela ajoute trop de complexité inutile à la bibliothèque de base. Notez qu’en termes de complexité, nous faisons référence à la fois à cette nouvelle interface et à ses utilisateurs.
Nous pensons que si le concepteur d’API ne se soucie pas de vérifier la propriété IsReadOnly à l’exécution et les exceptions qu’elle pourrait créer, alors il est acceptable d’utiliser l’interface IList dans ce cas ; S’ils sont prêts à fournir une API personnalisée vraiment propre d’un coup, alors dans ce cas, ils devraient montrer l’implémentation de l’interface IList et publier une API en lecture seule sur mesure. Cette dernière est typique des collections extraites du modèle d’objets. Bien que les développeurs se soient plaints de cette situation, les nouvelles opportunités offertes par les génériques l’emportent largement sur ce point central et le problème réside dans . NET 4 était largement ignoré auparavant. Cependant, cette décision a également suscité certaines réactions, dont nous aborderons plus tard.
Avec l’entrée. Une nouvelle fonctionnalité passionnante de .NET 4 a été ajoutée à l’exécution. Dans une version antérieure. .NET, lorsque les interfaces deviennent des types, ces interfaces sont trop limitées. Par exemple, même si le Client hérite de Person, il n’est pas possible de passer un objet de type IEnumerable <Customer>comme paramètre à une fonction de type IEnumerable<Person>. Avec l’ajout d’un support covariant, cette restriction a été partiellement levée.
Nous disons « partiellement » parce que dans certains cas, les gens devraient utiliser une interface avec une API riche d’un seul coup, plutôt que d’utiliser une interface IEnumerable. Même si l’interface IList n’est pas covariante, une interface de liste en lecture seule devrait l’être. Malheureusement, . L’équipe de la bibliothèque de base .NET a de nouveau décidé de ne pas corriger cette omission.
Puis l’introduction de WinRT et le retour de COM ont tout changé. L’interopérabilité COM était autrefois une technologie que les développeurs utilisaient lorsqu’ils n’avaient pas d’autre choix, mais elle est devenue un . La pierre angulaire de la programmation .NET. Et puisque WinRT expose les interfaces IVectorView <T>et IMapView<K, V> donc. .NET doit également être ajusté en conséquence.
Une caractéristique intéressante du programme WinRT est l’annonce d’API différentes mais similaires pour chaque plateforme de développement. Comme vous le savez peut-être déjà, tous les noms de méthodes sont représentés par camelCased [2], tandis que les développeurs C++ et .NET considèrent les noms des méthodes comme PascalCased [3]. Un autre changement plus radical est la correspondance automatique entre les interfaces C++ et .NET. Donc. Les développeurs .NET n’ont pas besoin de gérer l’espace de noms Windows.Foundation.Collections, ils continuent simplement à utiliser l’espace de noms System.Collections.Generic. Les interfaces IVectorView <T>et IMapView<K, V> seront converties à l’exécution en interfaces IReadOnlyList <T>et IReadOnlyDictionary<TKey, TValue>, respectivement.
Il convient de noter que ces noms d’interface en C++/WinRT sont plus précis dans une certaine mesure. Ces interfaces servent à représenter certaines vues d’une collection, mais l’interface ne garantit pas que la collection elle-même soit immuable. Même parmi ceux qui ont de l’expérience. Une erreur courante chez les développeurs .NET est de supposer que le type ReadOnlyCollection est une copie d’une collection immuable, alors qu’en réalité il ne s’agit que d’un wrapper pour une collection active (voir le post d’Andrew Arnott du même nom pour plus d’informations sur les collections en lecture seule, figées et immuables).
Bien que <T>l’interface IList ait tous les mêmes membres que l’interface IReadOnlyList<T>, et que toutes les listes de type IList <T>puissent être représentées comme des listes en lecture seule, IList <T>n’hérite pas d’IReadOnlyList<T>, ce qui peut être intéressant à découvrir. Immo Landwerth expliqua,
La raison pour laquelle cela fonctionne, c’est que ces interfaces en lecture seule sont de purs sous-ensembles d’interfaces de lecture-écriture, ce qui semble être une hypothèse raisonnable. Malheureusement, cette hypothèse ne correspond pas à la réalité, car chaque méthode sur chaque interface au niveau des métadonnées possède son propre emplacement (ce qui permet à des implémentations d’interfaces explicites de fonctionner). Ou autrement dit, la seule chance d’introduire une interface en lecture seule comme une classe de base variable est de revenir à . NET 2.0, c’est-à-dire quand ils ont été conçus à l’origine. Une fois complètement déployé, le seul changement possible est d’ajouter des marqueurs covariants et/ou onduleurs (représentés par « in » et « out » en VB et C#).
Lorsqu’on lui a demandé pourquoi il n’y avait pas <T>d’interface IReadOnlyCollection, Immo a répondu,
Nous avons envisagé ce design, mais nous avons estimé qu’ajouter un type ne fournissant que l’attribut Count n’apporterait pas beaucoup de valeur à la bibliothèque de base. Dans l’équipe de la bibliothèque de base, nous pensons que si une API commence à moins 1000, alors même fournir une certaine valeur ne suffit pas à justifier d’être ajoutée. La raison d’ajouter de nouvelles API inclut également un coût, par exemple les développeurs auront plus de concepts parmi lesquels choisir. Au début, nous pensions qu’ajouter ce type rendrait le code meilleur performant dans certains scénarios où l’on veut juste obtenir un compte puis faire quelque chose d’intéressant avec. Par exemple, ajouter en bloc à une collection existante. Cependant, dans ces scénarios, nous avons encouragé les gens à n’utiliser que l’interface IEnumerable<T>, et <T>dans le cas particulier d’avoir une instance qui implémente l’interface ICollection. Puisque tous nos types de collections intégrés implémentent cette interface, il n’y a eu aucun gain de performance dans ces scénarios les plus courants. Au fait, <T>la méthode d’extension Count() pour IEnumerable peut aussi faire cela. Ces nouvelles interfaces sont disponibles pour . NET 4.5 et . NET for Windows 8。
Notes de traduction
[1] Bibliothèque de la classe de base, abrégée en BCL. Pour plus d’informations sur la bibliothèque de la classe de base, veuillez participer à MSDN.
[2] chamelCased, nomenclature en bosse, également appelée casel minuscule. Le format est que le premier mot commence par une lettre minuscule ; La première lettre du deuxième mot est écrite en majuscule, par exemple : prénom, nomnom.
[3] PascalCased, nomenclature Pascal, également connue sous le nom de caisse supérieure du chameau. Le format est que la première lettre de chaque mot est écrite en majuscule, par exemple : Prénom, NomNom, CaseChameau. |