Что это за собственность? это необходимо? - PullRequest
2 голосов
/ 13 января 2010

При создании отображения я читаю, что свойство вашей коллекции должно выглядеть следующим образом:

  public virtual ReadOnlyCollection<Product> Products
  {
           get { return new ReadOnlyCollection<Product>(new List<Product>(_products).AsReadOnly()); }
  }

Почему так должно быть? кажется, что он возвращает новую коллекцию каждый раз, когда на нее ссылаются?

Ответы [ 7 ]

7 голосов
/ 13 января 2010

Он возвращает экземпляр класса-оболочки , который не позволяет вызывающим абонентам напрямую изменять коллекцию, которую вы возвращаете.

Если бы вы просто возвращали базовый список, любой вызывающий абонент мог бы изменить его таким образом, чтобы это могло нарушить класс, которому на самом деле принадлежит список.

Даже если вы вернули свой список как интерфейс только для чтения (скажем, IEnumerable или ICollection), ничто не мешает вызывающей стороне выполнить приведение во время выполнения и попасть в список.

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

В случае отображений ORM это позволяет объектной модели контролировать, в какой точке доступа вы можете изменять отношения между объектами.

4 голосов
/ 13 января 2010

Ваш код выглядит немного странно. Сначала он создает копию _products, затем делает ее доступной только для чтения, а затем снова оборачивает ее в коллекцию ReadOnlyCollection!

Если вы хотите открыть коллекцию, которая должна быть доступна только для чтения, сделайте что-то вроде этого:

private List<Product> _products = new List<Product>();

private ReadOnlyCollection<Product> _readonlyProducts =
    new ReadOnlyCollection(_products);

public ReadOnlyCollection<Product> Products
{
    get
    {
        return _readonlyProducts;
    }
}

Нет необходимости каждый раз воссоздавать коллекцию ReadOnlyCollection (или копировать, или дублировать коллекцию).

2 голосов
/ 13 января 2010

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

Чтобы создать коллекцию только для чтения, я бы сделал:

private List<Product> products = new List<Product>();

public ReadOnlyCollection<Product> Products { get { return products.AsReadOnly(); } }

Нет необходимости заключать метод AsReadOnly в оператор new ReadOnlyCollection. В качестве альтернативы вы можете сделать:

public ReadOnlyCollection<Product> Products { get { return new ReadOnlyCollection<Product>(products); } }

Однако я бы просто позвонил по номеру AsReadOnly, так как я думаю, что внутренне он все равно просто закроет ваш список.

1 голос
/ 13 января 2010

Я полагаю, что рекомендуется создать его таким образом, чтобы вы не могли изменить список в вызывающем коде. Обычно вы можете манипулировать им (поскольку он будет проходить по ссылке) - добавлять элементы, удалять элементы и т. Д. Это гарантирует, что вам придется использовать установщик для изменения внутреннего списка.

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

0 голосов
/ 13 января 2010

Полагаю, что _products равно ICollection<Product> или IEnumerable<Product> - в этом случае я думаю, что достаточно иметь new List<Product>(_products).AsReadOnly(). Если _products равно IList<Product>, то достаточно new ReadOnlyCollection<Product>(_products). Решение об использовании этого зависит от дизайна класса - в некоторых случаях даже лучше вернуть адаптер сбора, который скрывает каждый продукт, в экземпляр ProductView или ProductDTO только для чтения.

0 голосов
/ 13 января 2010

Этот код кажется мне избыточным ... почему не просто return _products.AsReadOnly()? (при условии, что _products представляет собой List<T>, массив или любой тип, который предоставляет метод AsReadOnly)

0 голосов
/ 13 января 2010

Он специально возвращает новую коллекцию, которую нельзя изменить. Кажется, немного глупо, хотя. Если я не ошибаюсь, это может быть:

public virtual ReadOnlyCollection<Product> Products
{
    get
    {
        return new List<Product>(_products).AsReadOnly();
    }
}

или, если _products - это уже какое-то List<Product>:

public virtual ReadOnlyCollection<Product> Products
{
    get
    {
        return _products.AsReadOnly();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...