En mi aplicación web ASP.net MVC4 utilizo IEnumerables, tratando de seguir el mantra para programar en la interfaz, no la implementación.
Return IEnumerable(Of Student)
vs
Return New List(Of Student)
La gente me dice que use List y no IEnumerable, porque las listas obligan a que se ejecute la consulta y IEumerable no.
¿Es esta realmente la mejor práctica? ¿Hay alguna alternativa? Me siento extraño usando objetos concretos donde podría usarse una interfaz. ¿Está justificado mi extraño sentimiento?
.net
programming-practices
asp.net-mvc
entity-framework
Rowan Freeman
fuente
fuente
Respuestas:
Hay momentos en los que hacer
ToList()
consultas en su linq puede ser importante para garantizar que sus consultas se ejecuten en el momento y en el orden que espera. Sin embargo, esos escenarios son raros y no hay nada de qué preocuparse demasiado hasta que realmente se encuentren con ellos.Para resumir, use en
IEnumerable
cualquier momento que solo necesite iteración, useIList
cuando necesite indexar directamente y necesite una matriz de tamaño dinámico (si necesita indexar en una matriz de tamaño fijo, simplemente use una matriz estándar).En cuanto al tiempo de ejecución, siempre puede usar una lista como
IEnumerable
variable, así que siéntase libre de devolver unIEnumerable
haciendo un.ToList();
, o pasar un parámetro como unIEnumerable
ejecutando.ToList()
elIEnumerable
para forzar la ejecución en ese momento. Solo tenga cuidado de que cada vez que fuerce la ejecución con.ToList()
usted no se aferre a laIEnumerable
variable a la que acaba de hacer eso y la ejecute nuevamente, o de lo contrario terminará duplicando las iteraciones en su consulta LINQ innecesariamente.En lo que respecta a MVC, realmente no hay nada especial que destacar aquí. Va a seguir las mismas reglas de tiempo de ejecución que el resto de .NET, creo que podrías tener a alguien que fue mordido por la confusión causada por la semántica de ejecución retrasada en el pasado y culpó a MVC de decirte que esto está de alguna manera relacionado, pero está no. La semántica de ejecución demorada confunde a todos al principio (e incluso por un buen tiempo después; pueden ser un poco complicados). Sin embargo, una vez más, no se preocupe por eso hasta que realmente se preocupe por asegurarse de que una consulta LINQ no se ejecute dos veces o requiera que se ejecute en un cierto orden en relación con otro código, en ese momento asigne su variable a sí mismo. ToList () para forzar la ejecución y estarás bien.
fuente
List
pasar alrededor de unList
implica que los contenidos de la lista van a ser modificados. Si desea devolver una colección, useIReadOnlyCollection
.List
es para usar dentro de métodos y para intercambiar entre métodos que modifican la lista. ¡Eso es!Hay dos problemas
En el momento en que se alcanza el ciclo "Datos de proceso", la consulta ya no es válida. Por ejemplo, si la consulta se ejecuta en un DataContext que ya se ha eliminado, su código arrojará una excepción. Este tipo de cosas se vuelve muy confuso cuando procesas una consulta en un contexto diferente al que la creaste.
Un problema secundario es que su conexión no se liberará hasta que se complete el ciclo "Datos de proceso". Esto es solo un problema si "Datos de proceso" es complejo. Esto se menciona en http://msdn.microsoft.com/en-us/library/bb386929.aspx :
Por lo tanto, estos problemas son la razón por la que se le recomienda asegurarse de que la consulta se ejecute realmente, por ejemplo, llamando
ToList()
. Sin embargo, como Jimmy sugiere, no hay nada que le impida devolver su Lista como IEnumerable.Como regla general, recomiendo evitar iterar sobre un IEnumerable más de una vez. Suponiendo que los consumidores de su código sigan esta regla, no considero una preocupación que alguien pueda acceder a la base de datos dos veces ejecutando la consulta dos veces.
fuente
Otro beneficio de enumerar
IEnumerable
temprano es que las excepciones se lanzarán en la ubicación adecuada. Esto ayuda a la depuración.Por ejemplo, si tiene una excepción de punto muerto dentro de una de sus vistas de Razor, no sería tan claro como si la excepción ocurriera durante uno de sus métodos de acceso a datos.
fuente
IEnumerable
que pueda arrojar probablemente esté cometiendo un error. LosIEnumerable
métodos diferidos deben dividirse en dos: un método no diferido verifica los parámetros y se configura, lanzando si es necesario (por ejemplo, debido a un argumento nulo). Luego, devuelve una llamada a la implementación privada que se aplaza. No creo que mis comentarios estén completamente en desacuerdo con su respuesta, pero sí creo que ha omitido un aspecto importante en su respuesta, que es el significado semántico de usarIEnumerable
vs. aList
(mutación) vs.IReadOnlyCollection
(sin beneficio para aplazamiento) .