Pergunta

Eu estou querendo saber qual destes seria considerado o mais limpo ou melhor usar e por quê.

Um deles expõe a uma lista de passageiros, que permitem que o suplemento de usuário e remover etc. Os outros couros da lista e só permitir que o usuário enumerá-los e adicionar usando um método especial.

Exemplo 1

class Bus
{
    public IEnumerable<Person> Passengers { get { return passengers; } }
    private List<Passengers> passengers;

    public Bus()
    {
        passengers = new List<Passenger>();
    }

    public void AddPassenger(Passenger passenger)
    {
        passengers.Add(passenger);
    }
}

var bus = new Bus1();
bus.AddPassenger(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

Exemplo 2

class Bus
{
    public List<Person> Passengers { get; private set; }

    public Bus()
    {
        Passengers = new List<Passenger>();
    }
}

var bus = new Bus();
bus.Passengers.Add(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

A primeira classe Eu diria que é melhor encapsulado. E, neste caso exato, que pode ser a melhor abordagem (desde que você provavelmente deve se certificar de esquerda no ônibus-lo do espaço, etc.). Mas eu acho que pode haver casos em que a segunda classe podem ser úteis também? Como se a classe não se importa o que acontece com essa lista, desde que ele tem um. O que você acha?

Foi útil?

Solução

No exemplo um, é possível transformar sua coleção.

Considere o seguinte:

var passengers = (List<Passenger>)bus.Passengers;

// Now I have control of the list!
passengers.Add(...);
passengers.Remove(...);

Para corrigir isso, você pode considerar algo como isto:

class Bus
{
  private List<Passenger> passengers;

  // Never expose the original collection
  public IEnumerable<Passenger> Passengers
  {
     get { return passengers.Select(p => p); }  
  }

  // Or expose the original collection as read only
  public ReadOnlyCollection<Passenger> ReadOnlyPassengers
  {
     get { return passengers.AsReadOnly(); }
  }

  public void AddPassenger(Passenger passenger)
  {
     passengers.Add(passenger);
  }
 }

Outras dicas

Na maioria dos casos eu consideraria exemplo 2 para ser aceitável, desde que o tipo subjacente era extensível e / ou exposto alguma forma de onAdded / onRemoved eventos para que sua classe interna pode responder a quaisquer alterações à coleção.

Neste Lista caso não é adequado como não há nenhuma maneira para a classe para saber se algo foi adicionado. Em vez disso você deve usar uma coleção porque o Collection classe tem vários membros virtuais (Insert, Remove, Set, Clear) que pode ser substituído e disparadores de eventos adicionado para notificar a classe de embrulho.

(Você também tem que estar ciente de que os usuários da classe pode modificar os itens na lista / coleção sem a classe pai que sabe sobre ele, para se certificar de que você não contar com os itens que estão sendo inalterada - a menos que eles são imutáveis, obviamente -. ou você pode fornecer eventos estilo OnChanged se você precisa)

Executar seus respectivos exemplos através FxCop e que deve dar-lhe uma dica sobre os riscos de expor List<T>

Eu diria que tudo se resume a sua situação. Eu normalmente ir para a opção 2, uma vez que é o mais simples, menos você tem uma razão de negócios para adicionar controles mais rígidos a ele.

A opção 2 é a mais simples, mas que permite que outras classes para adicionar / elementos Remover para a coleção, que pode ser perigoso.

Eu acho que uma boa heurística é considerar o que os métodos de mensagens publicitárias fazer. Se o seu AddPassenger (ou remover, ou outros) método é simplesmente retransmitindo a chamada para a coleção, em seguida, eu iria para a versão mais simples. Se você tem que verificar os elementos antes inseri-los, em seguida, a opção 1 é basicamente inevitável. Se você tem que manter o controle dos elementos inseridos / excluídos, você pode ir de qualquer maneira. Com a opção 2 você tem que registrar eventos na coleção para obter notificações, e com a opção 1 você tem que criar wrappers para cada operação na lista que você deseja usar (por exemplo, se você quiser Inserir, bem como adicionar), então eu acho ele depende.

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