2009-05-02 7 views
13

Hace poco le pregunté a alguien por qué prefería devolver una matriz fuertemente tipada a una IList. Siempre pensé que programar contra una interfaz era el programa más flexible y de mejor manera cuando se enfrentaba a un proyecto que tenía una larga vida. Así que me pareció extraño cuando respondió:regresando IList <T> contra Array en C#?

Por lo general, preferimos los tipos inmutables sobre los mutables. Las matrices son inmutables. IList no es.

No estoy del todo seguro de entender esta afirmación. ¿Alguien puede ayudar a aclarar esto?

Gracias por cualquier ayuda que ustedes puedan proporcionar.

Respuesta

10

Creo que tal vez pensó que como la propiedad de una matriz de longitud es inmutable, de alguna manera las matrices son más inmutables que IList o tal vez utilizó la palabra incorrecta y el hormigón intercambiado con inmutable. Quién sabe, pero es una respuesta extraña.

Creo que al devolver una lista hay algo ligeramente implícito en que está bien modificarla o que puede cambiar al devolver una matriz, no implica tanto.

Por ejemplo, si tenía un modelo de objetos en la parte superior de un repositorio y tenía un método como GetCars() que devolvía una Lista y un programador junior veía autos. Agregue (Coche c) ... ¿Creería que era completamente loco para pensar en automóviles. ¿Agregar (nuevo automóvil()) realmente podría agregar un automóvil al depósito? Las matrices son inherentemente más explícitas.

creo que el uso de la lista es más apropiado en propiedades, como Page.Controls.Add

prefiero matrices que regresan con más frecuencia que la lista por varias razones.

  • Hábito. Colecciones en 1.0/1.1 SUCKED

  • Prefiero que mis métodos devuelvan el objeto más ligero & que puedan. Si necesito hacer un Array a List, es trivial.

  • Se pueden usar en .net 1.1 y reduce la superficie de la refactorización. Si alguna vez tuve que admitir versiones anteriores del tiempo de ejecución, puedo reutilizar al menos parte de mi código o aplicar un modelo de objeto idéntico.

+0

¡Esto me dio el momento "ah-ha" que estaba buscando! La devolución de T [] desde un repositorio es menos "permeable" (como en la Ley de Extracciones Permeables). Si quisiera agregar algo al repositorio, lo llamaría método Agregar/Insertar ¿verdad? Por lo tanto, sería contraproducente/contra-intuitivo para mí asumir que al agregar algo a la lista devuelta podría participar en una Unidad de Trabajo o trabajar como se anticipó. ¡Cuando usas un IRepository, él es 100% correcto! Aunque la explicación que me dio fue más parecida a lo que dijiste: Array es más inmutable que IList en algunos aspectos. Muchas gracias! – mkelley33

+2

+1 para una lista de observación junior .Agregar podría pensar que es una buena idea (frente a no verlo con matriz) –

1

Quizás esta persona no sepa de lo que está hablando?

+1

Lo dudo. Es más probable que no sepa de qué "él" está hablando jajaja. – mkelley33

0

Básicamente dice que "preferimos estructuras que no se pueden cambiar fácilmente en el tiempo de ejecución, porque creemos que son menos vulnerables a los errores". Si eso es correcto en este caso es otra pregunta.

+0

Hmmm. Me gusta eso, pero no sé si es más valioso que programar contra un IList , ya que tengo más flexibilidad sobre la implementación. Gracias por la ayuda. Eso hace que su posición sea un poco más clara. – mkelley33

2

Yo tampoco lo entiendo. Las matrices son mutables, a excepción de su tamaño. Los elementos individuales todavía se pueden modificar. Tal vez quiso decir que las matrices son tipos de valores y las Listas son tipos de referencia. No lo sé.

De todos modos, probablemente debería echar un vistazo a Eric Lippert's opinion sobre el tema. También podría proporcionarle algo de munición para la discusión.

+0

Gracias. He leído ese artículo, por lo tanto, la confusión jajaja. Dadas las variadas opiniones sobre el tema de la mutabilidad (lo que es y lo que no es), tendría que ir con mi instinto y devolver IList hasta que se demuestre lo contrario. Permítanme decir que estoy en deuda con la persona que proporcionó la cita en la descripción de esta pregunta. "He-who-must-not-be-name-out-of-regard" es un sorprendente codificador e inspiración, pero no lo sigo ciegamente, así que tendré que esperar hasta escuchar su refutación de los argumentos proporcionados aquí. ! Gracias de nuevo. – mkelley33

+0

Pensando en ti mismo, ¡bien! :) Buena suerte para convencer a tu amigo. – Rik

7

Un punto que podría haber querido decir es que IList incluye los métodos Insertar, Eliminar y Agregar, por lo que la colección en sí misma se puede modificar. T [], por otro lado, no puede tener elementos agregados.

Debo añadir que FxCop recomienda devolver ReadOnlyCollection en su lugar. El indexador es de solo lectura, por lo que no puede cambiar los elementos, y los métodos Add y otros arrojan NotSupportedException.

+1

¡Genial! Eso es genial. Uso FxCop de vez en cuando en mi trabajo, y siempre me he preguntado sobre algunas de esas recomendaciones. ¡Gracias por la aclaración! – mkelley33

+1

+1 a la mejor respuesta corta cerca de la parte superior –

0

¿Quizás se refería al tamaño de la matriz como "inmutable"? Básicamente, declaras el tamaño una vez y estás atrapado con él. Con las listas, siempre puede usar "Agregar".

I supongo que si estás seguro de sobre el tamaño de la lista, tal vez la matriz es un poco más rápido?

+0

Eso es exactamente lo que asumí, pero realmente no sé lo que eso me compra cuando trabajo con el patrón de repositorio. ¡Gracias! – mkelley33

0

Bien. IList es mutable en el sentido de que puede agregar y eliminar elementos, en lugar de simplemente cambiar los elementos que ya están allí. Una matriz le permite jugar con elementos individuales, pero un índice en particular nunca se volverá completamente inválido. Hay varias razones para preferir la inmutabilidad: hace que el área de la corrupción accidental de datos sea mucho más pequeña, por ejemplo.

+0

Use ICollection , y devuelva uno que sea de solo lectura si devuelve uno. Las matrices implementan esta interfaz, de modo que uno puede elegir pasar interfaces o listas a dichos métodos. Count, Add and Remove se define en la interfaz genérica ICollection . – Lucero

12

Quien sea "él" es, está 100% mal con el tema. Las matrices son muy mutables. Esta es, de hecho, una de las razones para no devolver una matriz. No hay forma de evitar que una persona que llama cambie los elementos de una matriz a lo que ellos quieran.

La única manera en que un Arrray es inmutable es en su longitud. Una vez que se asigna una matriz, su longitud no se puede cambiar. Incluso las API como Array.Resize en realidad no cambian el tamaño de la matriz, solo asignan una nueva, copian los contenidos y devuelven la nueva matriz (por referencia en este caso).

Sin embargo, estoy de acuerdo en que hay muchos casos en los que es mejor devolver datos inmutables. El principal es que le permite devolver una referencia a una colección interna de una clase sin hacer una copia completa y al mismo tiempo evitar que la persona que llama se meta con su estado interno. La mayoría de las colecciones mutables no pueden hacer tales garantías.

+2

"en el que es válido ..." ¿quiere decir "en qué es mejor"? – peterchen

+1

@peterchen, sí, eso es lo que quise decir. corregido – JaredPar

+0

Bueno, yo no iría tan lejos ... "Es un codificador realmente increíble, pero creo que puede estar refiriéndose a algún aspecto en uno de los comentarios a continuación; sin embargo, no veo lo que esto "me compra" a mí o a mi programa. Si estoy usando un patrón de repositorio para devolver una lista de objetos, ¿por qué debe ser una matriz en lugar de IList ? – mkelley33

5

En principio tiene razón, pero que no sabe cómo poner en práctica de forma adecuada ...

normalmente Preferimos tipos inmutables sobre los mutables.

Eso es correcto. Los tipos inmutables son más fáciles de trabajar con

Las matrices son inmutables. IList no es.

Eso no es correcto. Ninguno de esos son inmutables.

Si desea devolver una colección que es inmutable, devuelva IEnumerable<T> o ReadOnlyCollection<T> (utilizando el método List<T>.AsReadOnly). Aún así, eso no protege a los objetos si ellos mismos no son inmutables. A pesar de que solo puede leer de las colecciones, puede cambiar los datos en cada objeto si lo permiten.

Además, debe considerar la "propiedad" de la colección que está devolviendo. Si está creando una matriz con el único propósito de devolverla, entonces no hay razón para no darle el control total. Si, por otro lado, está devolviendo una colección que es miembro de la clase, solo debe permitir el acceso tan pequeño como sea necesario.

1

La razón para utilizar una interfaz como tipo de devolución sobre el tipo real en sí es ocultar la implementación interna de la persona que llama. Esto permite que la implementación cambie el tipo real sin repurgencias al resto de la aplicación.

No tiene sentido copiar una colección utilizada internamente en una matriz para uso externo, sin más motivo que mutable o inmutable.

Los problemas separados son: - devuelve una lista de datos fuertemente tipados o no. IList o IList. Siempre se prefiere el uso de datos fuertemente tipados. - mutable o inmutable. ICollection, IList o IEnumerator Regrese con lo que quiere permitir a los datos. Para una lista de solo lectura devuelve solo un IEnumerator. Si la persona que llama puede modificar la colección, use ICollection o IList.

8

Siempre prefiero un ReadOnlyCollection. Todas las ventajas de una lista, pero de solo lectura.

Cuestiones relacionadas