2008-12-23 13 views
54

Según FXCop, la lista no se debe exponer en un modelo de objetos API. ¿Por qué se considera esto una mala práctica?¿Por qué se considera malo exponer la Lista <T>?

+4

Formulé la pregunta el 23 de diciembre de 2008. La pregunta a la que se vinculó fue publicada el 30 de diciembre de 2008. Diría que la mía fue lo primero. –

Respuesta

48

Estoy de acuerdo con alce-en-la-selva aquí: List<T> es un objeto sin restricciones, hinchado que tiene un montón de "equipaje" en el mismo.

Afortunadamente, la solución es simple: exponer IList<T> en su lugar.

Se expone una interfaz de barebones que la mayoría tiene todos los métodos List<T> 's (con la excepción de cosas como AddRange()) y no te limitan al tipo específico List<T>, que permite a sus consumidores de API para utilizar sus propias costumbres implementadores de IList<T>.

Para una mayor flexibilidad, considere exponer algunas colecciones al IEnumerable<T>, cuando corresponda.

+0

¿Qué recomendarías para un servicio web (donde un método no puede devolver/tomar una interfaz)? – kpollock

+1

kpollock: lamentablemente los servicios web SOAP * convertirán cualquier IList en una matriz de tipo T [] -> la serialización no admite el tipo de lista genérica. –

+6

El hecho de que utilice IList , no significa que guarde la memoria si eso es lo que está consiguiendo. Lo instancia con la nueva lista () y la variable IList aún apunta a una lista en la memoria. Aparte de eso, creo que suele ser beneficioso encapsular una colección en lugar de exponer directamente al código del cliente. – jlafay

3

Creo que no desea que sus consumidores agreguen nuevos elementos a su declaración. Una API debe ser clara y completa, y si devuelve una matriz, debe devolver la estructura de datos exacta. No creo que tenga nada que ver con T por decir, pero en lugar de regresar de una lista <> lugar de una matriz [] directamente

+4

-1. En particular, [las propiedades no deberían devolver matrices] (http://msdn.microsoft.com/en-us/library/0fss9skc%28v=VS.100%29.aspx). Mientras que los métodos pueden, en colecciones generales, secuencias enumerables e interfaces son más idiomáticas para C#. – TrueWill

25

Existen las 2 razones principales:

  • Lista <T> es un lugar tipo hinchado con muchos miembros no relevantes en muchos escenarios (está demasiado "ocupado" para los modelos de objetos públicos).
  • La clase no está sellado, pero no específicamente diseñado para ser extendida (no se puede anular cualquier miembro)
+7

Exactamente a la derecha.Aquí hay un enlace a Krzysztof Cwalina sobre el tema: http://blogs.msdn.com/kcwalina/archive/2005/09/26/474010.aspx –

5

Sólo se considera una mala práctica si está escribiendo una API que será utilizado por miles o millones de desarrolladores.

Las directrices de diseño de .NET framework están destinadas a las API públicas de Microsoft.

Si tiene una API que no está siendo utilizada por muchas personas, debe ignorar la advertencia.

+0

Ya sabes ... Estaba simplemente equivocado allí ... Actualizo mi respuesta. –

+0

Bueno ... entonces eliminaré mi comentario, que ya no es relevante. :) –

+2

Si bien es cierto que algunas de las reglas de FxCop son directrices de diseño del marco y pueden no ser apropiadas para algunos proyectos, incluso las bibliotecas diseñadas para equipos pequeños pueden beneficiarse de su seguimiento. ¿Alguna vez le ha dicho a 5 desarrolladores que tendrán que cambiar sus proyectos porque necesita hacer un cambio decisivo en una biblioteca (por ejemplo, observar los cambios como se menciona en @Kaagle)? ¿Alguna vez los desarrolladores de tu equipo han hecho algo que no esperabas, como modificar los contenidos de una propiedad de la lista que pretendías que fuera de solo lectura? – TrueWill

2

Una razón es porque List no es algo que pueda simular. Incluso en bibliotecas menos populares, he visto iteraciones que solían exponer un objeto List como IList debido a esta recomendación, y en versiones posteriores decidí no almacenar los datos en una lista (tal vez en una base de datos). Debido a que era un IList, no fue un cambio radical cambiar la implementación debajo de los clientes y aun así mantener a todos trabajando.

2

Una de las razones es que el usuario podrá cambiar la lista y el propietario de la lista no lo sabrá, mientras que en algunos casos debe hacer algunas cosas después de agregar/eliminar elementos a/de la lista. Incluso si no se requiere ahora, puede convertirse en un requisito en el futuro. Por lo tanto, es mejor agregar el método AddXXX/RemoveXXX al propietario de la clase y exponer la lista an IEnumerable o (lo cual es mejor en mi opinión) exponerlo como IList y usar ObservableCollection de WindowsBase.

+1

Exponer 'List ' como 'IList ' o 'IEnumerable ' no protege contra el usuario que modifica la lista (después de un molde en el caso de 'IEnumerable '). Si desea devolver una lista inmutable, devuelva 'ReadOnlyCollection ' o use 'IEnumerable .AsReadOnly()', que se puede devolver como 'IList '. – Joe

Cuestiones relacionadas