Quelqu'un peut-il m'aider avec une méthode d'extension Count
pour IEnumerable
(interface non générique).
Je sais que ce n'est pas pris en charge dans LINQ mais comment l'écrire manuellement?
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 cela 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
Comme Gerard le souligne dans les commentaires, IEnumerable
non générique n'hérite pas de IDisposable
donc l'instruction normale using
ne fonctionnera pas. Il est probablement encore important d'essayer de supprimer ces énumérateurs si possible - une méthode itérateur implémente IEnumerable
et peut donc être transmise indirectement à cette méthode Count
. En interne, cette méthode itérateur dépendra d'un appel à Dispose
pour déclencher ses propres instructions try
/finally
et using
.
Pour faciliter cela dans d'autres circonstances également, vous pouvez créer votre propre version de l'instruction using
qui est moins difficile 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 méthode Count
mise à jour 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;
}
yourEnumerable.Cast<object>().Count()
Au commentaire sur les performances:
Je pense que c'est un bon exemple d'optimisation prématurée, mais voilà:
static class EnumerableExtensions
{
public static int Count(this IEnumerable source)
{
int res = 0;
foreach (var item in source)
res++;
return res;
}
}
Différents types d'IEnumerable ont différentes méthodes optimales pour déterminer le nombre; malheureusement, il n'existe aucun moyen général de savoir quelle méthode sera la meilleure pour un IEnumerable donné, ni aucun moyen standard par lequel un IEmumerable peut indiquer laquelle des techniques suivantes est la meilleure:
Chacun de ces éléments sera optimal dans différents cas.
Je pense que le type choisi pour représenter votre séquence d'éléments aurait dû être ICollection au lieu de IEnumerable, en premier lieu.
ICollection
et ICollection<T>
fournit une propriété Count - plus - chaque ICollection implémente également IEnumearable.