369 Stimmen

Zählen Sie die Elemente aus einer IEnumerable<T> ohne Iteration?

private IEnumerable<string> Tables
{
    get
    {
        yield return "Foo";
        yield return "Bar";
    }
}

Sagen wir, ich möchte diese iterieren und etwas wie die Verarbeitung von #n von #m schreiben.

Gibt es eine Möglichkeit, wie ich den Wert von m herausfinden kann, ohne vor meiner Hauptiteration zu iterieren?

Ich hoffe, ich habe mich klar ausgedrückt.

392voto

Mendelt Punkte 35649

IEnumerable unterstützt dies nicht. Das ist so gewollt. IEnumerable nutzt die "Lazy Evaluation", um die gewünschten Elemente zu erhalten, kurz bevor Sie sie benötigen.

Wenn Sie die Anzahl der Elemente wissen wollen, ohne darüber zu iterieren, können Sie verwenden ICollection<T> hat sie eine Count Eigentum.

262voto

Daniel Earwicker Punkte 111630

Le System.Linq.Enumerable.Count Erweiterungsmethode auf IEnumerable<T> hat die folgende Umsetzung:

ICollection<T> c = source as ICollection<TSource>;
if (c != null)
    return c.Count;

int result = 0;
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
        result++;
}
return result;

Es wird also versucht, nach ICollection<T> die einen Count Eigenschaft, und verwendet diese, wenn möglich. Andernfalls wird es wiederholt.

Am besten ist es also, wenn Sie die Count() Erweiterungsmethode auf Ihrem IEnumerable<T> Objekt, da Sie auf diese Weise die bestmögliche Leistung erhalten.

100voto

Robert Paulson Punkte 16995

Ich füge nur ein paar zusätzliche Informationen hinzu:

Le Count() Erweiterung nicht immer iteriert. Betrachten Sie Linq to Sql, wo die Zählung an die Datenbank geht, aber anstatt alle Zeilen zurückzubringen, gibt sie die Sql Count() Befehl und gibt stattdessen dieses Ergebnis zurück.

Außerdem ist der Compiler (bzw. die Laufzeitumgebung) so intelligent, dass er die Objekte Count() Methode, wenn sie eine hat. Es ist also nicht wie andere Antwortende sagen, völlig unwissend zu sein und immer wieder zu iterieren, um Elemente zu zählen.

In vielen Fällen, in denen der Programmierer lediglich die if( enumerable.Count != 0 ) unter Verwendung der Any() Erweiterungsmethode, wie in if( enumerable.Any() ) ist mit der lazy evaluation von linq weitaus effizienter, da sie einen Kurzschluss erzeugen kann, sobald sie feststellen kann, dass es irgendwelche Elemente gibt. Außerdem ist es besser lesbar

15voto

Alternativ können Sie auch wie folgt vorgehen:

Tables.ToList<string>().Count;

13voto

Joel Coehoorn Punkte 377088

Ein Freund von mir hat eine Reihe von Blogbeiträgen verfasst, die veranschaulichen, warum dies nicht möglich ist. Er erstellt Funktionen, die eine IEnumerable zurückgeben, wobei jede Iteration die nächste Primzahl zurückgibt, bis hin zu ulong.MaxValue und der nächste Posten wird erst berechnet, wenn Sie ihn anfordern. Kurze Frage: Wie viele Artikel werden zurückgegeben?

Hier sind die Beiträge, aber sie sind ziemlich lang:

  1. Jenseits von Schleifen (bietet eine erste EnumerableUtility-Klasse, die in den anderen Beiträgen verwendet wird)
  2. Anwendungen von Iterate (Erste Durchführung)
  3. Verrückte Erweiterungsmethoden: ToLazyList (Leistungsoptimierungen)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X