Pergunta

Quais são as diretrizes de design da estrutura para expor uma coleção personalizada versus genérico? por exemplo

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

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

Vs.

public class Product
{
   public Collection<Image> Images{get; set;}
}
Foi útil?

Solução

Em geral, é melhor expor uma das interfaces, como IEnumerable<T>, ICollection<T> ou IList<T> em vez de uma classe concreta.

Isso fornece muito mais flexibilidade em termos de alteração da sua API interna. IEnumerable<T>, em particular, permite que você potencialmente modifique seus internos posteriormente para permitir a transmissão de resultados, o mesmo é o mais flexível.

Se você conhece os padrões de uso esperados de suas "coleções", exporá a API apropriada que fornece as menores restrições a você no futuro. Se, por exemplo, você sabe que as pessoas só precisam iterar seus resultados, expor IEnumerable<T>, para que você possa alterar para qualquer coleção posteriormente ou até mesmo mudar para apenas usar o rendimento diretamente.

Outras dicas

Se você estiver construindo uma API pública, considere usar uma coleção personalizada para as seguintes vantagens.

  • Extensibilidade - Você pode adicionar recursos à sua coleção personalizada no futuro sem alterar a API.

  • Compatibilidade para trás - você é livre para alterar os internos da sua aula de coleção como quiser, sem quebrar o código existente que os clientes programaram contra a coleção.

  • Também é mais fácil fazer com que potencialmente interromper mudanças com menos impacto. Talvez mais tarde você decida que não quer que seja um Collection<Image>, mas um tipo de coleção diferente - você pode adaptar seu ImageCollection classe para ter os mesmos métodos de antes, mas herdar de algo diferente - e o código do cliente provavelmente não será interrompido.

Se for apenas para código de uso interno, a decisão não é necessariamente tão importante e você pode decidir ir com "mais simples é melhor".

Um exemplo do topo da minha cabeça são as APIs do ARCGIS Server da ESRI - elas usam coleções personalizadas em suas APIs. Também usamos coleções personalizadas em nossas APIs, principalmente por esses motivos.

Eu iria para o segundo. O código do cliente precisa saber o tipo de imagem de qualquer maneira.

O primeiro significa apenas mais código.

A principal razão pela qual consigo pensar é que você pode ter alguns métodos específicos para uma coleção de imagens que operam nessa coleta. Então eu usaria uma classe de imagem para conter esses métodos. Encapsulamento clássico.

Além disso, apenas um aparte, você realmente deve expor apenas um getter para essa coleção e inicializar um campo de apoio à leitura com a coleção real. Você provavelmente deseja que as pessoas adicionem/removam itens à coleção, não substitua a coisa toda:

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

-Oisin

A única razão para usar Collection<T> é se você deseja conectar -se ao conjunto de métodos virtuais que permitem ver todas as mutações na lista subjacente. Isso permite que você faça operações que respondam a exclusão, implementar eventos, etc ...

Se você não está interessado em responder ou assistir a essas modificações de coleção, então um List<T> é um tipo mais apropriado.

Prefiro ter uma propriedade genérica pública para tornar os internos extensíveis, mas um campo privado seria o personalizado com a funcionalidade real.

Geralmente se parece com o seguinte:

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; }
   }
}

Eu também costumo fazer a classe de coleção personalizada aninhada dentro de uma classe diferente, o que me permite modificar alguns membros privados da classe pai durante Add/Remover.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top