Dans mon application Web ASP.net MVC4, j'utilise IEnumerables, en essayant de suivre le mantra pour programmer l'interface, pas l'implémentation.
Return IEnumerable(Of Student)
contre
Return New List(Of Student)
Les gens me disent d'utiliser List et non IEnumerable, car les listes forcent l'exécution de la requête et IEumerable ne le fait pas.
Est-ce vraiment la meilleure pratique? Y a-t-il une alternative? Je me sens étrange en utilisant des objets concrets où une interface pourrait être utilisée. Mon étrange sentiment est-il justifié?
.net
programming-practices
asp.net-mvc
entity-framework
Rowan Freeman
la source
la source
Réponses:
Il
ToList()
peut arriver que faire une requête sur vos requêtes linq soit important pour vous assurer que vos requêtes s'exécutent au moment et dans l'ordre que vous attendez. Ces scénarios sont cependant rares et rien ne devrait trop inquiéter jusqu'à ce qu'ils se heurtent vraiment à eux.Pour faire court, utilisez
IEnumerable
chaque fois que vous n'avez besoin que d'itération, utilisezIList
lorsque vous avez besoin d'indexer directement et avez besoin d'un tableau de taille dynamique (si vous avez besoin d'indexer sur un tableau de taille fixe, utilisez simplement un tableau standard).En ce qui concerne le temps d'exécution, vous pouvez toujours utiliser une liste comme
IEnumerable
variable, alors n'hésitez pas à retourner unIEnumerable
en faisant un.ToList();
, ou à passer un paramètre en tant queIEnumerable
en exécutant.ToList()
sur leIEnumerable
pour forcer l'exécution immédiatement et là. Veillez simplement à ce que chaque fois que vous forcez l'exécution avec.ToList()
vous ne vous accrochez pas à laIEnumerable
variable que vous venez de faire et l'exécutez à nouveau, sinon vous finirez par doubler inutilement les itérations de votre requête LINQ.En ce qui concerne MVC, il n'y a vraiment rien de spécial à noter ici. Il va suivre les mêmes règles de temps d'exécution que le reste de .NET, je pense que vous pourriez avoir quelqu'un qui a été mordu par la confusion causée par la sémantique d'exécution retardée dans le passé et blâmé MVC en vous disant que cela est en quelque sorte lié, mais c'est ne pas. La sémantique d'exécution retardée déroute tout le monde au début (et même pendant un bon moment par la suite; elles peuvent être délicates). Encore une fois cependant, ne vous inquiétez pas jusqu'à ce que vous vous souciez vraiment de garantir qu'une requête LINQ ne soit pas exécutée deux fois ou qu'elle ne soit pas exécutée dans un certain ordre par rapport à un autre code, auquel cas attribuez-vous votre variable à elle-même. pour forcer l'exécution et tout ira bien.
la source
List
--passer autour d'unList
implique que le contenu de la liste va être modifié. Si vous souhaitez renvoyer une collection, utilisezIReadOnlyCollection
.List
est à utiliser dans les méthodes et à échanger entre les méthodes qui modifient la liste. C'est ça!Il y a deux problèmes.
Au moment où la boucle "Process Data" est atteinte, la requête peut ne plus être valide. Par exemple, si la requête est exécutée sur un DataContext qui a déjà été supprimé, votre code lèvera une exception. Ce genre de chose devient très déroutant lorsque vous traitez une requête dans un contexte différent de celui où vous l'avez créée.
Un problème secondaire est que votre connexion ne sera pas libérée tant que la boucle "Process Data" ne sera pas terminée. Ce n'est un problème que si les «données de processus» sont complexes. Ceci est mentionné à http://msdn.microsoft.com/en-us/library/bb386929.aspx :
Donc, ces problèmes sont pourquoi vous êtes encouragés à vous assurer que la requête est réellement exécutée, par exemple en appelant
ToList()
. Cependant, comme suggère Jimmy , rien ne vous empêche de renvoyer votre liste en tant qu'IEnumerable.En règle générale, je recommande d'éviter d'itérer plusieurs fois sur un IEnumerable. En supposant que les consommateurs de votre code suivent cette règle, je ne considère pas que quelqu'un puisse frapper la base de données deux fois en exécutant la requête deux fois.
la source
Un autre avantage d’énumérer les
IEnumerable
précoce est que les exceptions seront levées à l'endroit approprié. Cela facilite le débogage.Par exemple, si vous avez obtenu une exception de blocage dans l'une de vos vues Razor, ce ne serait pas vraiment aussi clair que si l'exception s'était produite pendant l'une de vos méthodes d'accès aux données.
la source
IEnumerable
qui peut lancer est probablement une erreur. LesIEnumerable
méthodes différées doivent être divisées en deux: une méthode non différée vérifie les paramètres et configure, en lançant si nécessaire (par exemple, en raison d'un argument nul). Il renvoie ensuite un appel à l'implémentation privée qui est différé. Je ne pense pas que mes commentaires soient complètement en contradiction avec votre réponse, mais pensez que vous avez omis un aspect important dans votre réponse, qui est la signification sémantique de l'utilisationIEnumerable
vs aList
(mutation) vsIReadOnlyCollection
(aucun avantage pour report) .