Вопрос

Мне интересно, какой из них будет считаться самым чистым или лучшим в использовании и почему.

Один из них предоставляет список пассажиров, который позволяет пользователю добавлять, удалять и т. д. Другой скрывает список и позволяет пользователю только перечислять их и добавлять, используя специальный метод.

Пример 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);

Пример 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);

Первый класс, который я бы сказал, лучше инкапсулирован. И в этом конкретном случае это может быть лучшим подходом (поскольку вы, вероятно, должны убедиться, что в автобусе осталось место и т. Д.). Но я предполагаю, что могут быть случаи, когда второй класс также может быть полезен? Например, если классу все равно, что будет с этим списком, пока он есть. Что ты думаешь?

Это было полезно?

Решение

В первом примере можно изменить вашу коллекцию.

Примите во внимание следующее:

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

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

Чтобы это исправить, вы можете рассмотреть что-то вроде этого:

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

Другие советы

В большинстве случаев я бы посчитал пример 2 приемлемым при условии, что базовый тип был расширяемым и / или предоставлял некоторую форму событий onAdded / onRemoved, чтобы ваш внутренний класс мог реагировать на любые изменения в коллекции.

В этом случае List < T > не подходит, так как у класса нет возможности узнать, было ли что-то добавлено. Вместо этого вы должны использовать коллекцию, потому что коллекция & Lt; T & Gt; В классе есть несколько виртуальных членов («Вставить», «Удалить», «Установить», «Очистить»), которые можно переопределить и добавить триггеры событий для уведомления класса обтекания.

(Вы также должны знать, что пользователи класса могут изменять элементы в списке / коллекции без ведома родительского класса, поэтому убедитесь, что вы не полагаетесь на неизменность элементов - если только они очевидно, неизменны - или вы можете предоставить события стиля onChanged, если вам нужно.)

Проведите ваши соответствующие примеры через FxCop, и это должно дать вам подсказку о рисках разоблачения List<T>

Я бы сказал, что все сводится к вашей ситуации. Обычно я бы выбрал вариант 2, так как он самый простой, , если у вас нет бизнес-причин для добавления более жестких элементов управления.

Вариант 2 самый простой, но он позволяет другим классам добавлять / удалять элементы в коллекцию, что может быть опасно.

Я думаю, что хорошей эвристикой является рассмотрение того, что делают методы-оболочки. Если ваш метод AddPassenger (или Remove, или др.) Просто передает вызов коллекции, то я бы выбрал более простую версию. Если вам нужно проверить элементы до их вставки, то вариант 1 в основном неизбежен. Если вам нужно отслеживать вставленные / удаленные элементы, вы можете пойти любым путем. В варианте 2 вам нужно регистрировать события в коллекции для получения уведомлений, а в варианте 1 вы должны создавать оболочки для каждой операции в списке, которую вы хотите использовать (например, если вы хотите вставить, а также добавить), поэтому я думаю, это зависит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top