Hay un problema con el uso de IEnumerable<T> como un tipo de retorno?
FxCop queja sobre la devolución de List<T> (se aconseja volver Collection<T> lugar).

Bueno, yo siempre he sido guiado por una regla de «aceptar el que menos puede, pero el regreso al máximo».

Desde este punto de vista, volviendo IEnumerable<T> es una mala cosa, pero ¿qué debo hacer si quiero usar «lenta recuperación»? También, el yield palabra clave es una sorpresa.

InformationsquelleAutor Valentin | 2008-12-19

10 Comentarios

  1. 29

    Esta es realmente una pregunta de dos partes.

    1) hay nada inherentemente malo con el retorno de un IEnumerable<T>

    No hay nada en absoluto. De hecho, si usted está utilizando C# iteradores este es el comportamiento esperado. La conversión de una Lista de<T> o de otra clase de colección de forma anticipada no es una buena idea. Hacerlo es hacer una suposición sobre el patrón de uso por parte de su interlocutor. Me parece que no es una buena idea asumir nada acerca de la persona que llama. Pueden tener buenas razones de por qué quieren un IEnumerable<T>. Tal vez quieren convertir a una completamente diferente jerarquía de la colección (en cuyo caso la conversión a la Lista se desperdicia).

    2) ¿hay circunstancias en que puede ser preferible para devolver algo distinto de IEnumerable<T>?

    Sí. Aunque no es una gran idea para asumir mucho acerca de las personas que llaman, es perfectamente válido para tomar decisiones basadas en su propio comportamiento. Imagine un escenario en el que había un multi-threaded objeto que fue la formación de colas de solicitudes en un objeto que estaba siendo constantemente actualizado. En este caso la devolución de un raw IEnumerable<T> es irresponsable. Tan pronto como la colección se modifica el enumerable se invalida y se hará un execption a ocurrir. En lugar usted puede tomar una instantánea de la estructura y devolver ese valor. Dicen que en una Lista de<T> formulario. En este caso me acaba de devolver el objeto directo como estructura (o interfaz).

    Este es sin duda el más raro el caso.

  2. 27

    No, IEnumerable<T> es un buena cosa para volver aquí, ya que todo lo que prometen es «una secuencia de (escrito) de valores». Ideal para LINQ, etc, y perfectamente utilizable.

    La persona que llama puede poner fácilmente los datos en una lista (o lo que sea) – especialmente con LINQ (ToList, ToArray, etc).

    Este enfoque permite perezosamente carrete de vuelta valores, en lugar de tener que búfer de todos los datos. Sin duda una sorpresa. Escribí arriba otra utilidad de IEnumerable<T> truco el otro día, también.

    • todos los pensamientos sobre el por qué de fxcop se queja?
    • ¿De que se quejan sobre la devolución de IEnumerable<T>? Si es así, tomar con una pizca de sal… que no siempre es correcto.
    • Si se le pide que piensen sobre lo que realmente quiero volver, fxcop ha hecho su trabajo ;-p
    • Estoy bastante seguro de que sólo se queja acerca de la Lista de<T>, no IEnumerable<T>. A menos que yo haya excluido a algún lugar, no se quejan en mi código que devuelve IEnumerable<T>
  3. 4

    Acerca de su principio: «aceptar el que menos puede, pero el regreso a la máxima».

    La clave para manejar la complejidad de un programa grande es una técnica que se llama ocultar información. Si el método funciona mediante la construcción de un List<T>, no es a menudo necesario para revelar este hecho mediante la devolución de ese tipo. Si lo hace, entonces las personas que llaman pueden modificar la lista de regresar. Esto elimina su capacidad para hacer el almacenamiento en caché, o perezoso iteración con yield return.

    Para un mejor principio para una función a seguir es: «, se revela como poco como sea posible acerca de cómo se trabaja».

  4. 4

    IEnumerable está bien por mí, pero tiene algunos inconvenientes. El cliente tiene a enumerar para obtener los resultados. No tiene manera de comprobar el Recuento etc.
    La lista está mal porque te expongas demasiado control; el cliente puede agregar/quitar etc. a partir de ella y que puede ser una cosa mala.
    La colección parece el mejor compromomise, al menos en FxCop la vista.
    Yo siempre uso lo que parece apropiado en mi contexto (por ejemplo. si quiero devolver un sólo lectura de la colección de exponer la colección como tipo de retorno y devolución de la Lista.AsReadOnly() o IEnumerable para la evaluación diferida a través de rendimiento, etc.). Tener en una base de caso por caso

    • El cliente puede utilizar ToList(), método ToArray(), Count (), o lo que quiere.
    • pero los métodos de crear nuevos objetos. cualquier modificación realizada no se reflejen en el original objeto de la lista de
    • Buen punto! caso por caso parece mejor. Aunque yo prefiero la interfaz IEnumerable enfoque, favorece a la inmutabilidad.
  5. 3

    «aceptar el que menos puede, pero el regreso a la máxima de» es lo que yo defiendo. Cuando un método devuelve un objeto, ¿qué justificaciones tenemos para no devolver el tipo real y el límite de las capacidades del objeto mediante la devolución de un tipo base. Sin embargo, esto plantea una pregunta ¿cómo podemos saber lo que el «máximo» (de tipo real) será cuando el diseño de una interfaz. La respuesta es muy simple. Sólo en casos extremos en los que el diseñador de interfaz es el diseño de una interfaz abierta, la cual será ejecutada fuera de la aplicación/componente, ellos no saben lo que el rendimiento real puede ser. Una inteligente diseñador debe considerar siempre lo que el método debe hacer y lo que una óptima/genérico tipo de retorno debe ser.

    E. g. Si estoy en el diseño de la interfaz para recuperar un vector de objetos, y sé que el recuento de objetos devueltos va a ser variable, siempre voy a asumir un smart desarrollador siempre use una Lista. Si alguien planes para devolver un Array, me gustaría cuestionar sus capacidades, a menos que él/ella sólo se devuelve los datos de otra capa que él/ella no propio. Y esta es probablemente la razón por la FxCop defensores de ICollection (base común para la Lista y Matriz).

    El de arriba se dijo, hay un par de otras cosas a considerar

    • si los datos devueltos deben ser mutable o inmutable

    • si los datos devueltos ser compartida a través de múltiples personas que llaman

    Con respecto a la LINQ perezoso evaluaciones estoy seguro de que el 95%+ C# los usuarios no entienden el intestacies. Es tan no-oo-ish. OO promueve concreto de los cambios de estado en las invocaciones del método. LINQ evaluación diferida promueve tiempo de ejecución de los cambios de estado en la evaluación de la expresión del patrón (no es algo de no-usuarios avanzados siga siempre).

  6. 2

    Regresar IEnumerable<T> está bien si estás realmente solo devuelve una enumeración, y será consumida por el interlocutor como tal.

    Pero como los demás señalar, que tiene el inconveniente de que la persona que llama puede necesitar para enumerar si necesita cualquier otra información (por ejemplo, Contar). El .NET 3.5 método de extensión IEnumerable<T>.Conteo de enumerar detrás de las escenas, si el valor de retorno no se implementan ICollection<T>, que puede ser indeseable.

    Vuelvo a menudo IList<T> o ICollection<T> cuando el resultado es una colección internamente su método puede utilizar una Lista de<T> y devolver como está, o devolver la Lista<T>.AsReadOnly si desea proteger en contra de la modificación (por ejemplo, si estás de almacenamiento en caché de la lista internamente). AFAIK FxCop está muy feliz con cualquiera de estos.

  7. 2

    Un aspecto importante es que, al volver de un List<T> que son reales devolver un referencia. Que hace posible que una persona que llama para manipular a su lista. Este es un problema común—por ejemplo, una capa de Negocio que devuelve un List<T> a una interfaz gráfica de usuario de la capa.

    • Pero no te devuelven una referencia en cualquier momento que usted está devolviendo algo que no es un tipo de valor?
  8. 1

    Sólo porque usted dice que está regresando IEnumerable no significa que usted no puede devolver una Lista. La idea es reducir innecesarios de acoplamiento. Todo lo que la persona que llama la atención es acerca de obtener una lista de las cosas, más que el tipo exacto de la colección que se usa para contener esa lista. Si usted tiene algo que es respaldado por una matriz, a continuación, obtener algo parecido a Contar va a ser rápido, de todos modos.

    • Si la persona que espera un lista, a continuación, IList[<T>] sería una buena opción.
  9. 0

    Creo que tu propia guía es genial-si puedes ser más específico acerca de lo que está regresando sin un impacto en el rendimiento (no tiene, por ejemplo, crear una Lista de su resultado), hacerlo. Pero si su función legítimamente no sabe de qué tipo va a encontrar, como si en algunas situaciones, usted va a estar trabajando con una Lista y en algunos con una Matriz, etc., luego de regresar IEnumerable es el «mejor» que puede hacer. Piense en ello como el «máximo común múltiplo» de todo lo que pueda desear para volver.

  10. 0

    No puedo aceptar la respuesta que elijas. Hay maneras de lidiar con el escenario descrito, pero el uso de una Lista o de cualquier otra cosa que su uso no es uno de ellos. El momento en que el IEnumerable es devuelto, usted tiene que asumir que la persona que llama puede hacer un foreach. En ese caso no importa si el concreto es de tipo Lista o espaguetis. De hecho, sólo la indexación es un problema, especialmente si se eliminan los elementos.

    Cualquier valor devuelto es una instantánea. Puede ser el contenido actual de la interfaz IEnumerable en cuyo caso si la caché debe ser un clon de la copia en caché; si se supone que debe ser más dinámico (como el resuts de una consulta sql), a continuación, utilizar rendimiento; sin embargo, permite que el contenedor de mutar a voluntad y suministro de métodos como el Recuento y el indizador es una receta para el desastre en un multiproceso mundo. Ni siquiera he metido en la capacidad de la persona que llama para llamar a Añadir o Eliminar en un recipiente de su código se supone que para estar en control de.

    También la devolución de un tipo concreto, la encierra en una aplicación. Hoy internamente puede ser el uso de una lista. Mañana tal vez usted se convierte en multiproceso y desea utilizar un hilo de contenedor seguro o de una matriz o de una cola o de la toma de Valores de un diccionario o a la salida de una consulta Linq. Si usted encerrarse en un concreto tipo de retorno, a continuación, usted tiene que cambiar un montón de código o hacer conversiones antes de regresar.

Dejar respuesta

Please enter your comment!
Please enter your name here