47 votes

Calcul du compte pour IEnumerable (non générique)

Quelqu'un peut-il m'aider avec une méthode d'extension pour (interface non générique).

Je sais qu'il n'est pas pris en charge dans LINQ, mais comment l'écrire manuellement?

47voto

Lasse Espeholt Points 11944
<pre><code></code><p><em>Pour le commentaire sur la performance:</em></p><p>Je pense que c'est un bon exemple d'optimisation prématurée, mais ici vous allez:</p><pre><code></code></pre></pre>

42voto

Daniel Earwicker Points 63298

La forme la plus simple serait:

public static int Count(this IEnumerable source)
{
    int c = 0;
    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
            c++;
    }
    return c;
}

Vous pouvez ensuite améliorer cette situation en interrogeant ICollection:

public static int Count(this IEnumerable source)
{
    var col = source as ICollection;
    if (col != null)
        return col.Count;

    int c = 0;
    using (var e = source.GetEnumerator())
    {
        while (e.MoveNext())
            c++;
    }
    return c;
}

Mise à jour

Que Gérard points dans les commentaires, non générique IEnumerable de ne pas hériter IDisposable ainsi, la normale, using déclaration ne fonctionne pas. Il est probablement toujours important de tenter de se défaire de ces agents recenseurs si possible - un itérateur méthode implémente IEnumerable et peut donc être transmis indirectement à cette Count méthode. En interne, que l'itérateur de la méthode en fonction d'un appel à l' Dispose pour déclencher sa propre try/finally et using des déclarations.

Pour rendre cela facile, dans d'autres circonstances aussi, vous pouvez faire votre propre version de l' using déclaration qui est moins tatillons au moment de la compilation:

public static void DynamicUsing(object resource, Action action)
{
    try
    {
        action();
    }
    finally
    {
        IDisposable d = resource as IDisposable;
        if (d != null)
            d.Dispose();
    }
}

Et la mise à jour de Count méthode serait alors:

public static int Count(this IEnumerable source) 
{
    var col = source as ICollection; 
    if (col != null)
        return col.Count; 

    int c = 0;
    var e = source.GetEnumerator();
    DynamicUsing(e, () =>
    {
        while (e.MoveNext())
            c++;
    });

    return c;
}

4voto

supercat Points 25534

Les différents types de IEnumerable ont différentes méthodes optimales pour déterminer le comte; malheureusement, il n'y a pas d'usage général, de moyens de savoir quelle méthode est la meilleure pour tout IEnumerable, ni même un standard moyen par lequel un IEmumerable peut indiquer laquelle de ces techniques est le meilleur:

  1. Demandez tout simplement à l'objet directement. Certains types d'objets qui prennent en charge IEnumerable, tels que Tableau, Liste et de la Collecte, ont des propriétés qui peuvent directement rapport au nombre d'éléments en eux.
  2. Énumérer tous les éléments, de les jeter, et de compter le nombre d'éléments énumérés.
  3. Énumérer tous les éléments dans une liste, et ensuite utiliser la liste s'il est nécessaire d'utiliser de l'énumération de nouveau.

Chacun des ci-dessus sera optimale dans différents cas.

-1voto

IEnumerable<DataRow> results = from resultsRow in myDataTable.AsEnumerable()
                                               where resultsRow.Field<string>("strParentAccountID") == objReport.AccountID
                                               select resultsRow;

results .ToList().Count

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