72 votes

Retourne un IEnumerator vide

J'ai une interface qui, entre autres choses, implémente une méthode "public IEnumerator GetEnumerator()", de sorte que je peux utiliser l'interface dans une instruction foreach.

J'implémente cette interface dans plusieurs classes et dans l'une d'entre elles, je souhaite renvoyer un IEnumerator vide. Pour l'instant, je procède de la manière suivante :

public IEnumerator GetEnumerator()
{
    ArrayList arr = new ArrayList();
    return arr.GetEnumerator();
}

Cependant, je considère qu'il s'agit d'une mauvaise manipulation, et je ne peux m'empêcher de penser qu'il existe une meilleure façon de retourner un IEnumerator vide. Existe-t-il une meilleure façon de retourner un IEnumerator vide ?

102voto

Jon Skeet Points 692016

C'est simple en C# 2 :

public IEnumerator GetEnumerator()
{
    yield break;
}

Vous avez besoin du yield break pour forcer le compilateur à le traiter comme un bloc itérateur.

Ce sera moins efficace qu'un itérateur vide "personnalisé", mais c'est un code plus simple...

4 votes

Il est vraiment inutile d'essayer de rivaliser avec vous dans une question C# :-)

11 votes

@Konamiman : Pas du tout. Vous vous souvenez de la question LINQ à laquelle vous avez répondu et que vous avez ensuite supprimée, en remarquant que la valeur de l'attribut était obligatoire ? Cela m'a échappé !

0 votes

Notez que cette solution ne fonctionne pas dans tous les cas : il n'est pas possible de combiner la rupture de rendement avec le renvoi d'un autre énumérateur. if (some case) { yield break; } else { return SomeStaticMethodThatGivesEnumerable();} // does not work . Dans ce cas, utilisez l'option Vide de l'autre solution. Merci à toutes les personnes concernées.

95voto

user287107 Points 4383

Il existe une fonction supplémentaire dans le cadre :

public static class Enumerable
{
    public static IEnumerable<TResult> Empty<TResult>();
}

Grâce à cela, vous pouvez écrire :

var emptyEnumerable = Enumerable.Empty<int>();
var emptyEnumerator = Enumerable.Empty<int>().GetEnumerator();

13 votes

Pour obtenir un IEnumerator<T> au lieu d'un IEnumerable<T> : Enumerable.Empty<Whatever>().GetEnumerator() ;

13voto

Konamiman Points 20578

Vous pourriez mettre en œuvre une classe fictive qui implémente IEnumerator, et renvoyer une instance de cette classe :

class DummyEnumerator : IEnumerator
{
    public object Current
    {
        get
        {
            throw new InvalidOperationException();
        }
    }

    public bool MoveNext()
    {
        return false;
    }

    public void Reset()
    {
    }
}

6voto

thecoop Points 23695

La méthode que j'utilise consiste à utiliser l'énumérateur d'un tableau vide :

public IEnumerator GetEnumerator() {
    return new object[0].GetEnumerator();
}

Il peut également être utilisé pour un IEnumerator ou un IEnumerable générique (utiliser un tableau du type approprié).

0 votes

J'aime bien cette solution. Elle est simple. C'est direct. C'est économique. Elle est élégante (du moins en apparence). Je me demande s'il y a des inconvénients à utiliser quelque chose comme ça. Quoi qu'il en soit, je l'achèterais à nouveau.

1voto

ArsenMkrt Points 24447

Vous pouvez mettre en œuvre les interfaces IEnumerator et IEnumerable, et renvoyer false à partir de la fonction MoveNext de l'interface IEnumerable.

private class EmptyEnumerator : IEnumerator
{

    public EmptyEnumerator()
    {
    }

    #region IEnumerator Members

    public void Reset() { }

    public object Current
    {
        get
        {
            throw new InvalidOperationException();
        }
    }
    public bool MoveNext()
    { return false; }
}

public class EmptyEnumerable : IEnumerable
{

    public IEnumerator GetEnumerator()
    {
        return new EmptyEnumerator();
    }
}

1 votes

D'après la documentation MSDN, Current devrait lancer une exception dans ce cas ( msdn.microsoft.com/en-us/library/ )

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X