2010-07-30 6 views
10

Je cherche des règles empiriques pour appeler ToList/ToArray/MemoizeAll(Rx) sur IEnumerables, par opposition à retourner la requête elle-même lors du retour IEnumerable de quelque chose. Souvent, je trouve qu'il vaut mieux renvoyer simplement la requête et laisser l'appelant décider si une liste est nécessaire ou non, mais parfois il peut revenir et vous mordre à l'arrière en raison de la nature paresseuse de linq.Règles de base pour quand appeler ToList lors du retour des résultats LINQ

Je veux recueillir des directives telles que:

Appel ToList si:

  • vous créer de nouveaux objets
  • vous avez des effets secondaires dans votre requête
  • (par exemple dans une sélection.)

Sinon, renvoyez la requête

+4

Vous devriez avoir (rarement?) Des effets secondaires dans votre requête. –

Répondre

23

Tout d'abord, vous ne devriez JAMAIS avoir d'effets secondaires dans une requête. C'est une pire pratique. Les requêtes doivent répondre à une question, ne pas produire d'effet.

La réponse à votre question est: renvoyer une requête lorsque l'appelant attend une requête; renvoie une liste lorsque l'appelant attend une liste. Lorsque vous concevez votre méthode, décidez ce que l'appelant est le plus susceptible de vouloir, implémentez-le, puis document.

Pour déterminer si l'appelant veut une requête ou une liste, pensez à les différences entre les requêtes et les listes:

  • requêtes sont toujours à jour. Si les objets/bases de données/tout ce que la requête interroge change son contenu, les résultats de la requête changeront si vous réexécutez la requête. Les listes ne changent pas leur contenu et, par conséquent, les listes sont périmées. Si votre appelant nécessite les dernières données puis leur donner une requête. S'ils ont besoin de un instantané des données qu'ils peuvent inspecter à loisir puis leur donner une liste.

  • Les requêtes sont potentiellement coûteuses à exécuter pour obtenir leurs résultats. Les listes ne coûtent pas cher pour obtenir leurs résultats. Si l'appelant est susceptible de vouloir interroger le résultat plusieurs fois et s'attend à obtenir les mêmes résultats à chaque fois, donnez-lui une liste. La construction d'une requête est rapide. L'exécution d'une requête pour construire une liste est lente. Une liste obtient toujours tous les résultats d'une requête. L'appelant peut vouloir restreindre davantage la requête, en ne prenant par exemple que les dix premiers éléments. Si l'appelant ne veut pas ou ne doit pas prendre en charge l'itération complète sur l'ensemble de la requête, donnez-lui une requête; ne prenez pas cette décision en leur nom et donnez-leur une liste.

  • les requêtes sont minuscule. Les listes sont gros. De nombreuses requêtes peuvent être itérées sur n éléments dans l'espace O (1); une liste avec n éléments occupe l'espace O (n). Si le résultat est énorme, le mettre dans une liste est probablement inefficace.

  • et ainsi de suite.

Il n'y a pas de réponse facile. La réponse est la même que la réponse à tout autre problème de conception: Examinez tous les avantages et les inconvénients de chaque solution possible dans le contexte de ce que l'utilisateur de la fonction souhaite le plus probablement, puis choisissez une solution de compromis raisonnable.

3

Retour ToList si:

  • Vous ne voulez pas ou de soins pour l'évaluation de la requête paresseuse.

Edit:

De plus, ToList de retour si:

  • Vous utilisez une sorte de LINQ to cadre SQL (LLBLGen, EF, etc.), et vous devez faire une opération sur la liste qui ne peut pas être traduite en SQL par le framework.
+0

+1 pour l'édition. Surtout si les opérations suivantes entraîneraient une attaque de la base de données plusieurs fois par la même requête. Utilisez le profileur de serveur SQL pour déterminer où utiliser 'ToList()'. – Necros

1

vous ToList() lorsque vous voulez une liste d'objets pour votre résultat.

+0

+1: Je ne pense pas que cela puisse être mieux que cela en règle générale. –

+0

@Lasse: Oui. Cette réponse n'explique pas * quand * nous voudrions un 'List '. –

+1

Parce qu'il y a un million de cas d'utilisation où vous voulez utiliser un 'List ' et un million de cas d'utilisation (qui semblent étrangement les mêmes) où vous ne voulez pas l'utiliser. C'est entièrement spécifique au scénario en cours. Quelle est la ligne directrice pour quand utiliser une variable? Quelle est la ligne directrice pour quand utiliser une chaîne? Vous ne pouvez pas vraiment créer une ligne directrice qui le dit. Maintenant, je suis d'accord, vous pouvez décrire les caractéristiques d'une liste, puis dire "quand vous en avez besoin, vous voulez utiliser une liste", mais il demande des directives sur * le retour des données *. Vous ne pouvez pas, parce que vous ne voulez pas utiliser une liste ou non. –

2

Utilisez ToList si vous devez exécuter des fonctions personnalisées sur les données renvoyées par LINQ to SQL.

2

Utilisez ToList avant de quitter le bloc using qui contient votre DataContext.

Renvoie une requête lorsque l'appelant est susceptible de fournir des critères de filtrage supplémentaires qui seront utilisés par les index pour réduire le nombre de lignes de résultat et/ou d'E/S de la base de données.