2009-10-09 15 views
11

¿Cuáles son las recomendaciones para exponer una colección personalizada frente a una genérica? por ejemploColección personalizada frente a Colección genérica para métodos públicos

public class ImageCollection : Collection<Image> 
{ 
    ... 
} 

public class Product 
{ 
    public ImageCollection {get; set;} 
} 

VS

public class Product 
{ 
    public Collection<Image> Images{get; set;} 
} 

qué casos le considere crear una colección personalizada? ¿Cuáles son los pros y los contras de cada método?

+1

Una tercera posibilidad sería exponer un IList of Image. –

+0

En conjunto me refiero a IList, List etc cuando digo "Colección". Creo que la pregunta todavía se aplica incluso si es para una lista o IList etc. –

+0

Las pautas de .NET fx son rápidas para señalar que hay un aspecto de legibilidad, también, favoreciendo la colección personalizada sobre una lista genérica en muchos casos –

Respuesta

9

En general, lo mejor es exponer una de las interfaces, tales como IEnumerable<T>, ICollection<T> o IList<T> en lugar de una clase concreta.

Esto le proporciona mucha más flexibilidad en términos de cambiar su API interna. IEnumerable<T>, en particular, le permite modificar potencialmente su interior más tarde para permitir la transmisión de resultados, por lo que es el más flexible.

Si conoce los patrones de uso esperados de sus "colecciones", debe exponer la API adecuada que le ofrezca las menores restricciones en el futuro. Si, por ejemplo, usted sabe que las personas solo necesitan repetir los resultados, exponga IEnumerable<T>, para poder cambiar a CUALQUIER colección más adelante, o incluso cambiar a simplemente usar retorno de rendimiento directamente.

+0

Creo que estoy de acuerdo con usted al usar la "colección" simplista para la API interna. ¿Pero expondría IEnumerable , ICollection o IList en su API pública? ¿O crearía una "colección" personalizada que implemente IEnumerable , ICollection o IList , cubriendo así los pros womp descritos anteriormente? –

+4

No. El libro de directrices de diseño del marco actualmente (ahora) sugiere exponer IEnumerable , IList , etc., en API públicas. Le brindan MÁS flexibilidad para cambiar su implementación interna sin romper la API pública. Si implementa una colección personalizada, estará bloqueado para ese tipo para siempre, a menos que quiera romper la compatibilidad de la API. –

5

Iría por la segunda. El código de cliente debe saber el tipo de imagen de todos modos.

El primero solo significa más código.

1

La única razón para utilizar Collection<T> es si desea conectar el conjunto de métodos virtuales que le permite ver todas las mutaciones de la lista subyacente. Esto le permite realizar operaciones como responder a las eliminaciones, implementar eventos, etc.

Si no está interesado en responder o ver estas modificaciones de recopilación, entonces un List<T> es un tipo más apropiado.

13

Si está creando una API pública, considere utilizar una colección personalizada para las siguientes ventajas.

  • Extensibilidad: puede agregar funciones a su colección personalizada en el futuro sin cambiar la API.

  • Compatibilidad con versiones anteriores: puede cambiar las partes internas de su clase de colección como lo desee, sin romper el código existente que los clientes han programado para la colección.

  • También es más fácil realizar posibles cambios de rotura con menos impacto. Tal vez más tarde decidas que no quieres que sea Collection<Image>, sino un tipo de colección diferente: puedes personalizar tu clase ImageCollection para tener los mismos métodos que antes, pero heredar de algo diferente, y es probable que el código del cliente no se rompa .

Si es sólo para el código de uso interno, la decisión no es necesariamente tan importante, y usted puede decidir ir con "más simple es mejor".

Un ejemplo fuera de lo común son las API de ArcGIS Server de ESRI: usan colecciones personalizadas en sus API. También usamos colecciones personalizadas en nuestra API principalmente por estos motivos.

+1

En realidad, cambiar el tipo de base de una clase se considera un cambio brusco (por ejemplo, si el código del cliente lo asigna a una "Colección "), pero generalmente no tendrá importancia. – SLaks

+0

Nunca recomendaría referirme a ninguna API de ArcGIS como un ejemplo de un "buen" .NET a seguir. Usan colecciones personalizadas porque están atrapados con el ajuste de COM, pero también usan iteradores de estilo java en todas partes en la API .NET, no exponen IEnumerable o IEnumerable donde deberían, y muchas otras funciones que hacen la vida muy difícil. –

+0

@Slaks - muy cierto. Lo mitiga mucho de todos modos. – womp

5

La razón principal que se me ocurre es que quizás desee tener algunos métodos específicos para una colección de imágenes que operan en esa colección. Entonces usaría una clase ImageCollection para contener esos métodos. Encapsulación clásica

Además, solo debe dejar al descubierto un getter para esa colección e inicializar un campo de respaldo de solo lectura con la colección real.Es posible que desee personas para añadir/quitar elementos a la colección, no reemplazar toda la cosa:

class Product { 
    private readonly Collection<Image> _images; 
    public Product() { _images = new Collection<Image>(); } 
    public Collection<Image> Images { get { return _images; } } 
} 

-Oisin

+2

+1 para la propina en el captador. –

1

Prefiero tener una propiedad genérica pública para hacer las partes internas extensibles, pero un campo privado sería el personalizado con la funcionalidad real.

Por lo general, tiene el siguiente aspecto:

public interface IProduct 
{ 
    ICollection<Image> Images { get; } 
} 

public class Product : IProduct 
{ 
    private class ImageCollection : Collection<Image> 
    { 
     // override InsertItem, RemoveItem, etc. 
    } 

    private readonly ImageCollection _images; 
    public ICollection<Image> Images 
    { 
     get { return _images; } 
    } 
} 

también a menudo hacen la clase de colección personalizada anidada dentro de una clase diferente, lo que me permite modificar algunos miembros privados de la clase padre durante añadir/quitar.

Cuestiones relacionadas