Существует ли интерфейс коллекции .NET, который предотвращает добавление объектов? - PullRequest
24 голосов
/ 01 февраля 2010

У меня есть класс, который поддерживает список объектов другого класса.Список объектов является публичной собственностью.Я хотел бы запретить пользователям добавлять и удалять объекты непосредственно в список следующим образом:

      MyObject.MyListProperty.Add(object);

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

У меня есть несколько идей:

  • создать потомка List<T> и переопределить добавить и удалить
  • вернуть свежую копию списка через метод получения свойства (список относительно короткий, не более чем30 объектов)

Есть ли какой-нибудь интерфейс коллекции, в котором нет функции «Добавить и удалить»?

Редактировать:
Я собираюсь пойти с ReadOnlyCollection<T>.Причина в том, что упакованную коллекцию можно обновить, и изменения будут немедленно видны в объекте только для чтения (см. Примеры кода MSDN для ReadOnlyCollection<T> и AsReadOnly()).Это позволяет создавать список только для чтения только один раз.

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

Ответы [ 7 ]

36 голосов
/ 01 февраля 2010

Вы можете использовать ReadOnlyCollection - оберните свою коллекцию в это и верните ReadOnlyCollection пользователям вашего класса:

return new ReadOnlyCollection(innerCollection);

Или используя метод AsReadOnly класса List<T>:

return innerCollection.AsReadOnly();

Интерфейс IEnumerable будет делать то, что вам нужно, так как он имеет только один элемент GetEnumerator(), который позволит вам перебирать только элементы.

5 голосов
/ 01 февраля 2010

Ваш самый простой вариант - представить ваш список как один из следующих IEnumerable , ICollection ReadOnlyCollection через открытое свойство.

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

public class MyList<MyType>
{
    private List<MyType> items;

    public MyList()
    {
        items = new List<MyType>();
    }

    public IEnumerable Items { get { return items.AsEnumerable(); } }
    public Add(MyType item)
    {
        // do internal processing
        items.Add(item);
    }
}
5 голосов
/ 01 февраля 2010

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

В противном случае IEnumerable<T> не имеет ни Add, ни Remove, поэтому вы можете сделать что-то вроде:

private List<int> _myList;
public IEnumerable<int> MyList
{
   get
   {
      return this._myList.ToList();
   }
}

Я бы предпочел перейти на IEnumerable<T> (+ copy), как для ReadOnlyCollection<T>, потому что: изменения в вашем базовом списке (из которого создана ваша коллекция только для чтения) немедленно появятся в вашем экземпляре чтения -только коллекция это может вызвать проблемы с блокировками и переходами:)

2 голосов
/ 01 февраля 2010

Из коробки только IEnumerable<T> предоставит это, не раскрывая никаких Add и Remove открытых методов, которые могут обмануть клиента в получении исключения во время выполнения.

Если вы хотите, чтобы ваш публичный API явно указывал, что коллекция доступна только для чтения, и вам нужен индексатор, вам придется написать свою собственную оболочку вокруг существующих List<T> или T[].

0 голосов
/ 01 февраля 2010

ICollection (неуниверсальная версия) получила только IEnumerable + Count

0 голосов
/ 01 февраля 2010

На самом деле не отвечает на ваш вопрос, но является полезной информацией, если вы решите реализовать одну из двух ваших идей: вы можете использовать ToArray, чтобы создать копию и вернуть массив.

Или вы можете что-то сделатькак это: http://en.csharp -online.net / CSharp_Generics_Recipes% E2% 80% 94Making_Read-Only_Collections_the_Generic_Way

0 голосов
/ 01 февраля 2010

Вы могли бы просто дать им объект, который всегда возвращает перечислитель, который они могут использовать для доступа к структуре?

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