Je sais que c'est probablement doesnt matter/affecter les performances, pour la plupart, mais je déteste l'idée de faire un IEnumerable
et faire .Count()
. Est-il un IsEmpty
ou NotEmpty
soit une fonction? (semblable à la stl vide())
Réponses
Trop de publicités?Vous souhaitez IEnumerable.Tout() la méthode d'extension (.Net Framework 3.5 et ci-dessus). Il évite de comptage sur les éléments.
Vous pouvez utiliser des méthodes d'extension comme Tout() ou la fonction Count(). Count() est plus coûteux que le Tout(), car elle doit exécuter l'ensemble de l'énumération, comme d'autres l'ont souligné.
Mais dans le cas de l'évaluation différée (par exemple, une méthode qui utilise rendement), soit on peut être coûteux. Par exemple, avec les suivants en IEnumerable
mise en œuvre, chaque appel à l'un ou à Compter devra assumer le coût d'un aller-retour à la base de données:
IEnumerable<MyObject> GetMyObjects(...)
{
using(IDbConnection connection = ...)
{
using(IDataReader reader = ...)
{
while(reader.Read())
{
yield return GetMyObjectFromReader(reader);
}
}
}
}
Je pense que la morale est:
Si vous avez seulement un
IEnumerable<T>
, et vous voulez faire plus que de simplement énumérer (par exemple, l'utilisation de nombre ou de Tout), puis examiner d'abord la convertir en une Liste (méthode d'extension ToList). De cette manière, vous garantissez à seulement énumérer une fois.Si vous êtes à la conception d'une API qui renvoie une collection, envisager de revenir
ICollection<T>
(ou mêmeIList<T>
) plutôt que d'IEnumerable<T>
comme beaucoup de gens semblent à recommander. En faisant ainsi, vous êtes le renforcement de votre contrat, afin de garantir l'absence d'évaluation différée (et donc pas de multiples d'évaluation).
Veuillez noter que je suis en train de dire que vous devriez envisager de retourner une collection, pas toujours renvoyer une collection. Comme il y a toujours des compromis, comme en témoignent les commentaires ci-dessous.
@KeithS pense que vous devriez ne jamais céder sur un DataReader, et bien que je ne jamais dire jamais, je dirais que c'est généralement des conseils judicieux qu'une Couche d'Accès aux Données doit retourner un
ICollection<T>
plutôt qu'un paresseux-évaluéesIEnumerable<T>
, pour les raisons KeithS donne dans son commentaire.@Ours Singe note que l'instanciation d'une Liste peut être cher dans l'exemple ci-dessus si la base de données renvoie un grand nombre de dossiers. C'est vrai aussi, et dans certains (probablement rares) cas, il peut être opportun d'ignorer @KeithS, les conseils et le retour d'un paresseux-évalué énumération, à condition que le consommateur est en train de faire quelque chose qui n'est pas trop de temps (par exemple, de générer des valeurs d'agrégation).
Gardez à l'esprit que IEnumerable est juste une interface. La mise en œuvre derrière il peut être très différente d'une classe à l'autre (pensez à Joe exemple). La méthode d'extension IEnumerable.Tout() doit être une approche générique et peut ne pas être ce que vous voulez (performance sage). Yossarian propose un moyen qui doivent travailler pour un grand nombre de classes, mais si l'implémentation sous-jacente n'utilisons pas de "rendement", vous pouvez tout de même payer un prix.
En règle générale, si vous vous en tenez à des collections ou des tableaux enveloppé dans une interface IEnumerable, puis Cristobalito et Yossarian probablement de la meilleure des réponses. Ma conjecture est que de l'intégré .Tout() la méthode " ext " n'a que Yossarian recommande.