On a posé quelques reprises à quelques reprises sur la manière dont vous pouvez mettre en œuvre un énumérateur bidirectionnel ( Ici , ici ). Ma question n'est pas comment em> (qui est triviale pour la plupart des cas), mais pourquoi em> aucun type de tel existe dans la plate-forme .NET. public interface IBidirectionalEnumerator<T> : IEnumerator<T>
{
bool MovePrev();
}
6 Réponses :
Parce que personne n'a pensé à ce sujet, ou personne ne pensait que ce serait particulièrement utile ou parce qu'il n'y avait pas assez de budget ou ... P>
Ce n'est pas vraiment nécessaire, n'est-ce pas? Vous pouvez facilement le mettre en œuvre vous-même. Peut-être que l'équipe de BCL pensait que cela ne valait pas la peine de la mise en œuvre, des tests, de la documentation, etc. Ne sous-estimez jamais le coût d'une fonctionnalité, cela peut sembler "facile", mais il dispose de coûts. P>
particulièrement parce qu'une seule interface que personne implémente ne semblerait étrange, n'est-ce pas? Vous attendez-vous à la liste, au tableau, etc. Pour mettre en œuvre l'interface, qui est beaucoup de travail à la fin. P>
Comme Raymond Chen dirait, toutes les fonctionnalités commencent avec -100 points.
aussi, quelle serait la motivation pour cela? Prise en charge de la langue pour l'itération "en arrière"? P>
Le motif d'itérateur ne donne pas beaucoup de poids au concept de "directionnalité" d'un ensemble d'éléments. C'est un modèle simple pour fournir une interface simple pour itération sur un ensemble. p>
Ce n'est pas complètement vrai. C # nécessite uniquement la méthode MOVENNEXT code> et la propriété code> actuelle code> pour fonctionner. Il ne s'appuie pas sur l'interface du tout.
En fait, ienumerator
foreach code>. Tant que votre classe a une méthode
getenumerator () code> qui ne prend aucun paramètre et renvoie un objet qui a un objet
actuel {obtenir; } code> Propriété et un
VOID MOVENEXTEXT () CODE> méthode, puis
foreach code> fonctionnera assez joyeusement avec elle.
Greg: vraiment ?! Donc, l'ienumerator est effectivement dactylographié? C'est une révélation.
Ce n'est pas typé de canard. C # Vérifiez simplement si le type implémente l'interface ou comporte les méthodes / propriétés nécessaires. L'IL produit pour une boucle de Foreach n'utilise pas iEnumerable nulle part, donc pas besoin de canard.
C'est ce que je voulais dire par dactylographie de canard. C'est le typing de canard de compilation, vrai, mais il s'agit toujours d'un canard.
Je pense que les itérateurs C ++ sont un idiome de programmation assez courant: cprogramming.com/taturial/stl/antitrant .html
Lorsque vous concevez un cadre, vous devez prendre des décisions concernant de faire des choses à différents niveaux d'abstraction. Le compromis est que si vous choisissez d'exposer des éléments à un niveau d'abstraction élevé, vous obtiendrez une généralisation au coût de perte de contrôle grain fin. Si vous choisissez d'exposer des éléments à des niveaux d'abstraction inférieurs, votre concept ne peut pas également être généralisé, mais vous pouvez contrôler les détails à un niveau inférieur. P>
C'est une décision de conception. La mise en œuvre des deux sera coûteuse et créera un cadre plus gonflé et vous devrez prendre en charge les deux en ajoutant des fonctionnalités. Vous aurez besoin de préserver la compatibilité en arrière à l'avenir. Ce n'est pas une chose sage d'ajouter tout ce que vous pouvez penser à la BCL sans s'assurer qu'il a un avantage significatif. P>
Évidemment, il existe de nombreux types de collecte qui ne peuvent pas implémenter cela, car
movenext () code> est destructeur ou modifie l'état de la collection sous-jacente. P> blockQuote>
movenext () code> n'est pas destructif. En fait, si l'état de la collection sous-jacente est modifié entre le moment où le
ienumerator code> a été créé et l'heure
movenext () code> est appelé, l'appel à
MOVENNEXT () code> échouera. p>
Le but de
ienumerator code> est de itérer sur tous les éléments d'une collection une fois, dans l'ordre natif de la collection si la collection a une ordonnance natale.
ienumerator code> n'est pas conçu comme un périphérique de navigation de collecte, tel que celui que l'on pourrait trouver en C ++. P>
Quel serait l'appareil de navigation de la collection C # alors? Je veux dire la version C # des itérateurs C ++?
Une question plus grande est pourquoi .NET n'en mettant pas en œuvre IReaderByByIndex, qui serait à son tour hérité d'IList. Un tel type n'aurait rien ajouté au travail requis pour produire des implémentations ilistes en lecture-écriture et aurait réduit les travaux nécessaires pour produire des implémentations en lecture seule (qui mettront en place IReaderByByDex, plutôt qu'Ilist). P>
Ce n'est pas trop utile pour réfléchir à une telle "Pourquoi" s) cependant. .NET est ce que c'est. Le seul moyen de remédier à la situation de .NET 5.0 serait d'autoriser un moyen de déclarer qu'une interface qui implémente une propriété en lecture-écriture peut être réputée implémenter implicitement une version en lecture seule (afin de permettre à IList d'hériter un covariant IreadableByDex sans avoir à ajouter une méthode d'obtention explicite). P>
Il y a quelque chose de très mal avec votre conception de collection si elle est énumérée dessus change son état.
D'accord. Mais il y a bien quelques collections qui devraient changer tout en énumérant, comme une collation ou une file d'attente.
Sauf si vous utilisez iEnumérable enveloppé sur un type de streaming ou une ressource système telle qu'un streamerrieur ou une liste de fichiers.
En outre, alors que toutes les collections sont des énumérations, toutes les énumérations ne sont pas des collections.
Convenu Matthew, mon commentaire était trop court. Les effets secondaires sont bien acceptables (les flux sont en effet un bon exemple et les requêtes sont une autre), mais elles doivent être localisées. Je pense que je suis enumérant sur quelque chose de plusieurs fois, même lors de la mise en marche entre les énumérateurs, devrait être cohérent. Sinon, vous faites des choses très inincutrices.