2010-01-13 2 views
2

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

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

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

ответ

7

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

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

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

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

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

+0

поэтому, по сути, убедитесь, что вы не пытаетесь изменить список из этого «конца» отображения, вам нужно изменить его на конце, где вы установили cascade = update/save/etc. и inverse = ложный ? – mrblah

+1

Да. Это способ контролировать точку доступа, через которую вы можете изменить коллекцию. – LBushkin

1

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

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

0

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

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

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

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

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

4

Ваш код выглядит немного странным. Сначала он создает копию _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

В ваших коллекциях нет есть, которые всегда должны быть прочитаны. Это зависит от того, для чего предназначен этот список.Если это действительно просто список ссылок, вы можете даже вернуть 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, как я думаю, что внутренне он просто будет оборачивать список для вас в любом случае.

0

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