Question

Je suis curieux de voir comment la méthode SingleOrFallback a été mis en œuvre dans MoreLinq et découvert quelque chose Je ne l'avais pas vu auparavant:

    public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback)
    {
        source.ThrowIfNull("source");
        fallback.ThrowIfNull("fallback");
        using (IEnumerator<T> iterator = source.GetEnumerator())
        {
            if (!iterator.MoveNext())
            {
                return fallback();
            }
            T first = iterator.Current;
            if (iterator.MoveNext())
            {
                throw new InvalidOperationException();
            }
            return first;
        }
    }

Pourquoi le IEnumerator<T> dans un communiqué de using? Est-ce quelque chose qui doit être pensé lors de l'utilisation du foreach sur un IEnumerable<T> aussi?

question de côté: Qu'est-ce que cette méthode exactement? Est-il revenir l'élément de secours chaque fois que la séquence source ne contient pas exactement un élément?

Était-ce utile?

La solution

IEnumerator<T> étend IDisposable, de sorte que vous devez ont dans une déclaration à l'aide. foreach fait automatiquement. (Le IEnumerator non générique ne pas étendre IDisposable mais le compilateur C # génère encore du code pour appeler Dispose conditionnelle. Ce fut l'un des (rares) changements entre C # 1.0 et 1.2, où 1.2 est la version expédition avec .NET 1.1, pour une raison quelconque.)

Voici un article expliquant pourquoi il est important dans le contexte des blocs itérateur.

Quant à ce que la méthode fait:

  • Si la séquence est vide, retourner l'élément de secours
  • Si la séquence a exactement un élément, retourner
  • Si la séquence a plus d'un élément, lancer une exception

PS: Nice voir MoreLinq est une certaine attention:)

Autres conseils

Certains agents recenseurs se comportent mal si Dispose est pas appelé; cela est tout aussi vrai pour les non génériques que les génériques (les non génériques requièrent que le code soit de type de canard l'appel Éliminez ou bien jeter à IDisposable puis appeler IDisposable.Dispose). Il est bon que par habitude de faire en sorte que les objets IEnumerator obtenir disposés; Je considère qu'il est nécessaire pour l'exactitude de toute routine qui accepte un IEnumerable de type inconnu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top