2010-08-24 23 views
47

He visto esta pregunta publicada anteriormente, pero no estoy satisfecho de haber entendido las ramificaciones completas. El problema es qué tipo de devolución debería tener una capa de datos que utiliza el retorno de linq-a-sql para una máxima flexibilidad y capacidad de consulta. Esto es lo que he leído/encontrado:List, IList, IEnumerable, IQueryable, ICollection, ¿cuál es el tipo de devolución más flexible?

  1. IEnumerable es limitada y sólo permite la lectura de marcha hacia adelante. IEnumerable es el más genérico. Lo que he encontrado es que IEnumerable permite operaciones de consulta frente a la sintaxis de la extensión.

  2. La lista permite una mayor flexibilidad debido a las operaciones de inserción.

  3. Se deben usar colecciones en lugar de listas para habilitar las colecciones de solo lectura.

  4. IQueryable nunca debe usarse, debe "usarse y apagarse". IQueryable no devuelve una lista sino que genera una sintaxis de consulta para la base de datos.

Siento que tengo una mejor idea de las compensaciones, pero todavía no está seguro acerca de algunas cosas:

  1. ¿Por qué elegir las variantes de interfaces más de los tipos de hormigón? Es decir, IList o ICollection versus List o Collection. ¿Qué beneficio obtendré?

  2. Veo que las operaciones de extensión funcionan, pero ¿funcionará también la sintaxis de consulta ampliada?

  3. Alguien me sugirió que use AsQueryable() antes. Pero, ¿por qué haría esto si no tengo conexión a la base de datos? Parece que los métodos de extensión funcionan independientemente.

+9

Elimina la clase "Lista" de tu pregunta. IList, IEnumerable, IQueryable, etc. son todas las interfaces, mientras que "List" es una clase. La clase "Lista" es una manzana entre naranjas en su pregunta. – riwalk

+2

@Stargazer que es parte de la pregunta, ¿cuál es el beneficio de usar IList vs List. Estoy escribiendo algunos ejemplos ahora. –

+0

@Curtis, eso es lo que estoy diciendo: List implementa IList, y por lo tanto * is * an IList. Son manzanas y naranjas, y no creo que entiendas la diferencia. Una mejor manera de reformular una pregunta que implica la diferencia entre los dos sería: "¿Cuál es la diferencia entre devolver una clase y devolver una interfaz?" – riwalk

Respuesta

29

Colecciones generalmente no son muy útiles para las devoluciones DAL, debido a una colección no garantiza implícitamente orden. Es solo un cubo de artículos. Un IList, por otro lado, garantiza implícitamente el orden. Así que estamos en IEnumerable o IList. La siguiente pregunta sería: ¿está el objeto List "en vivo"? es decir, ¿está conectado al respaldo de datos para que cuando agregue un elemento al IList, se refleje en el DB? Para LINQ-to-SQL, este no es el caso. Más bien, se supone que debes adjuntar entidades a las tablas. Entonces, a menos que suministre este cableado adicional, una Lista es superflua. Quédese con IEnumerable.

+0

@Rex Bien, esto tiene sentido. ¿Por qué devolvería IList por usar la Lista concreta? ¿Cuál es el beneficio para los casos que tiene sentido? –

+3

@Rex: aunque estoy de acuerdo con su conclusión, respetuosamente, sugeriría que el DAL no debería ordenar colecciones. Eso pertenece a la lógica del cliente/consumidor/negocio. es decir 'MyDal.ListCustomers(). OrderBy (InvoiceDate)'. –

+0

@ P.Campbell Me preocupa la velocidad de esta operación, especialmente cuando no se requiere. –

3

1) Lo mejor es devolver un IList para que los resultados puedan colocarse en cualquier objeto que implemente esa interfaz, en lugar de forzar al llamante a utilizar una lista. Por ejemplo, la persona que llama podría desear que los resultados vuelvan a una ArrayList, esto no sería posible si tuviera los resultados devueltos a una lista. ArrayList no hereda de List, pero implementa IList.

+10

Buena respuesta, excepto que es incorrecta. La persona que llama no controla cómo se devuelven los resultados. Si tengo un método "IList GetCustomers()" y el tipo de concreto devuelto es realmente "List", la persona que llama no puede decir ArrayList results = GetCustomers(); ver http://stackoverflow.com/questions/539436/cast-interface-to-its-concrete-implementation-object-or-vice-versa – User

7

Siempre debe devolver una interfaz en lugar de un tipo concreto, esto es evidente ya que especifica el comportamiento permitido sin vincular al consumidor a una implementación específica.

En cuanto a la interfaz a devolver, debe pensar en el propósito del método y las intenciones de la persona que llama. Si devuelve una colección, ¿debería la persona que llama poder modificar la colección? p.ej. agregar/eliminar elementos? si todo lo que necesitan hacer es enumerarlo (hacer un foreach), entonces simplemente debe devolver un IEnumerable.

33

IEnumerable <> => permite el uso de 'foreach' en una colección

ICollection <> => Como IEnumerable <> + Agregar(), remove(), contar, Borrar(), contiene(), IsReadOnly, CopyTo()

IList <> => Como ICollection <> + esta [int], Insert(), IndexOf(), RemoveAt(). es decir. Agrega el tipo de indexación list operator

• ¿Se puede usar 'return yield ???' junto con IEnumerable <> para devolver solo 1 objeto a la vez. Aquí es de donde proviene el poder real de IEnumerable (no simplemente devolviendo una lista o una matriz).

• Al devolver una lista, decida qué puede exponerse al usuario y devuelva el tipo apropiado.

• Tal vez sea mejor para devolver un ICollection <> IList o <> y si el cliente sólo necesita código para enumerar la lista que puede echarlo a un IEnumerable <>. es decir. Dado ICollection SomeMethod() ... El usuario podría invocarlo como IEnumerable widgets = SomeMethod()

+0

Además, IEnumerable es covariante donde IList NO lo es. Por lo tanto, si devolviera IList y luego, en algún momento, pasara a una lista, tendría que repetir y volver a agregarla a la lista concreta. Con IEnumerable, puede decir (IEnumerable myPersons = new List ();) y eso funcionará. – JamesM

+0

¿Me falta algo o es incorrecta esta lista de métodos para cada interfaz? ** ICollection ** tiene '.CopyTo()' y '.Count()', el resto pertenece a ** IList **. –

Cuestiones relacionadas