Il me manque quelque chose de simple ici.
Prenez le code suivant:
public IEnumerable<int> getInt(){
for(int i = 0; i < 10; i++){
yield return i;
}
}
Je peux appeler ça avec:
foreach (int j in obj.getInt()){
//do something with j
}
Comment puis-je utiliser la méthode getInt sans la boucle foreach:
IEnumerable<int> iter = obj.getInt();
// do something with iter ??
Merci.
ÉDITE
Pour ceux qui se demandent pourquoi je voudrais cela. Je répète deux choses:
IEnumerator<int> iter = obj.getInt().GetEnumerator();
foreach(object x in xs){
if (x.someCondition) continue;
iter.MoveNext();
int n = iter.current();
x.someProp = n;
etc...
}
Vous pouvez obtenir une référence à la Enumerator
, en utilisant la méthode GetEnumerator
, puis vous pouvez utiliser la MoveNext()
pour continuer et utilisez la propriété Current
pour accéder à vos éléments:
var enumerator = getInt().GetEnumerator();
while(enumerator.MoveNext())
{
int n = enumerator.Current;
Console.WriteLine(n);
}
Mon conseil: ne plaisante pas avec les enquêteurs. Caractérisez votre problème comme une série d'opérations sur des séquences. Écrivez du code pour exprimer ces opérations. Laissez les opérateurs de séquence se charger de gérer les énumérateurs.
Voyons donc si j'ai bien compris. Vous avez deux séquences. Disons {2, 3, 5, 7, 12} et {"grenouille", "crapaud"}. L'opération logique que vous souhaitez effectuer est, par exemple, "passer par la première séquence. Chaque fois que vous trouvez un nombre divisible par trois, obtenez l'élément suivant dans la deuxième séquence. Faites quelque chose avec la paire résultante (nombre, amphibiens)".
Facile à faire. Tout d'abord, filtrez la première séquence:
var filtered = firstSequence.Where(x=>x%3 == 0);
Ensuite, fermez la séquence filtrée avec la deuxième séquence:
var zipped = filtered.Zip(
secondSequence,
(y, z)=> new {Number = x, Amphibian = y});
Et maintenant, vous pouvez parcourir la séquence zippée et faire ce que vous voulez avec les paires:
foreach(var pair in zipped)
Console.WriteLine("{0} : {1}", pair.Number, pair.Amphibian);
Peasy facile, ne plaisante pas avec les enquêteurs.
Que dis-tu de ça?
IEnumerator<int> iter = obj.getInt();
using(iter) {
while(iter.MoveNext()) {
DoSomethingWith(iter.Current)
}
}
utilisation de la boucle:
for (var enumerator = getInt().GetEnumerator(); enumerator.MoveNext(); )
{
Console.WriteLine(enumerator.Current);
}
Bien que les réponses acceptées soient correctes, notez que IEnumerator.Current n'est pas défini avant le premier appel à MoveNext ().
Si vous parcourez un tableau secondaire, vous voudrez quelque chose comme:
IEnumerable<Foo> Foo() { ... }
int AssignValues(List<TakesFoo> data) {
var count = 0;
var foo = Foo().GetEnumerator();
// Step into the first element of the array;
// doing this does not discard a value from the IEnumerator
if (foo.MoveNext()) {
foreach (var x in data) {
x.SetFoo(foo.Current);
count += 1;
if (!foo.MoveNext()) {
break;
}
}
// Return count of assigned values
return count;
}
Il est important de mentionner que le devoir de la boucle foreach
est de disposer l'énumérateur si l'instance implémente IDisposable
. En d'autres termes, foreach
doit être remplacé par quelque chose comme:
var enumerator = enumerable.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// do stuff
}
}
finally
{
var disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}