L'écriture personnalisée IEnumerator<T> avec les itérateurs
Comment puis-je écrire une coutume IEnumerator<T>
de mise en œuvre qui doit conserver une certaine état et toujours de commencer à utiliser un itérateur blocs de la simplifier? Le mieux que je puisse vous arriver, c'est quelque chose comme ceci:
public class MyEnumerator<T> : IEnumerator<T> {
private IEnumerator<T> _enumerator;
public int Position {get; private set;} //or some other custom properties
public MyEnumerator() {
Position = 0;
_enumerator = MakeEnumerator();
}
private IEnumerator<T> MakeEnumerator() {
//yield return something depending on Position
}
public bool MoveNext() {
bool res = _enumerator.MoveNext();
if (res) Position++;
return res;
}
//delegate Reset and Current to _enumerator as well
}
public class MyCollection<T> : IEnumerable<T> {
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return GetEnumerator();
}
public MyEnumerator<T> GetEnumerator() {
return new MyEnumerator<T>();
}
...
}
OriginalL'auteur Alexey Romanov | 2009-01-11
Vous devez vous connecter pour publier un commentaire.
Pourquoi voulez-vous écrire un itérateur de classe? Le point de l'ensemble d'un bloc itérateur est de sorte que vous n'avez pas à...
c'est à dire
Si vous ajoutez plus de contexte (i,e, pourquoi le ci-dessus ne peuvent pas travailler), nous pouvons probablement vous aider plus.
Mais si possible, éviter d'écrire une classe iterator. Ils sont beaucoup de travail, et il est facile de se tromper.
Par la manière, vous n'avez pas vraiment besoin de s'embêter avec
Reset
- c'est en grande partie obsolète, et ne devrait pas vraiment être jamais utilisée (car il ne peut pas être invoquée à travailler pour l'arbitraire d'un agent recenseur).Si vous voulez consommer intérieure d'un itérateur, c'est très bien aussi:
ou si vous avez seulement un agent recenseur:
Vous pouvez également ajouter de l'etat (comme un n-uplet) à la chose que vous avez rendement:
Enfin, vous pouvez utiliser un style LINQ extension/délégué approche, avec un
Action<int,T>
pour l'approvisionnement de la position et de la valeur à l'appelant:Sorties:
si votre bloc itérateur prend quelque chose de IDisposable, il faut alors utiliser un
using
de l'instruction qui sera ensuite correctement nettoyé dans la plupart des conditions normales d'utilisation,OriginalL'auteur Marc Gravell
J'aurais d'accord avec Marc ici. Écrire un énumérateur de classe complètement vous-même si vous voulez vraiment (juste parce que vous pouvez?) ou tout simplement utiliser un interator bloc et le rendement des déclarations et être fait avec elle. Personnellement, je ne suis jamais toucher énumérateur classes de nouveau. 😉
OriginalL'auteur peSHIr
@Marc Gravel
C'est précisément pourquoi je veux utiliser
yield
machines à l'intérieur de mon itérateur, pour faire le gros du travail.Oui, ça marche. Cependant, c'est une allocation supplémentaire à chaque étape. Si je suis intéressé seulement dans
T
à la plupart des étapes, c'est une surcharge je n'ai pas besoin si je peux l'éviter.Cependant, votre dernière suggestion m'a donné une idée:
OriginalL'auteur Alexey Romanov
J'ai fait assez simple Itérateur qui emprunte la valeur par défaut Énumérateur de faire le plus (vraiment tous) de l'œuvre. Le constructeur prend un
IEnumerator<T>
et ma mise en œuvre simplement les mains-il de l'œuvre. J'ai ajouté uneIndex
domaine à mon personnalisée Itérateur.J'ai fait un exemple simple ici: https://dotnetfiddle.net/0iGmVz
Pour utiliser cet Itérateur d'installation que vous auriez quelque chose comme ceci dans votre Collection personnalisée/List classe:
Maintenant
foreach
et d'autres fonctions intégrées obtiendrez personnalisé de votre agent recenseur, et tout comportement que vous ne voulez pas remplacer normalement utilisées dans la mise en œuvre.OriginalL'auteur Chakrava