Вопрос

У меня есть следующий класс:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

   public ArrayList MyList
   {
       get { return mMyList;}
   }
}

Я хочу, чтобы пользователи могли получать mMyList, поэтому я раскрыл " get " однако через свойство я не хочу, чтобы они вносили изменения в объект (т. е. MyList.Add (new Class ());), чтобы вернуться в мой класс.

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

Возможно ли это?

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

Решение

С ArrayList вы довольно ограничены, потому что в BCL нет не предназначенного для чтения неуниверсального класса коллекции. Быстрое и грязное решение - вернуть тип IEnumerable.

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

Это на самом деле не помешает кому-либо приводить в ArrayList, но также не разрешит редактирование по умолчанию

Вы можете вернуть список только для чтения, вызвав ArrayList.ReadOnly. Однако тип возвращаемого значения - ArrayList, поэтому пользователь все равно сможет компилировать с .Add, но это приведет к ошибке времени выполнения.

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

Используйте ArrayList.ReadOnly () метод для создания и возврата обертки только для чтения вокруг списка. он не будет копировать список, а просто создаст оболочку только для чтения. Чтобы получить проверку во время компиляции, вы, вероятно, захотите вернуть оболочку только для чтения, как IEnumerable, как предлагает @Jared.

public IEnumerable MyList
{
     get { return ArrayList.ReadOnly(mMyList); }
}
  

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

     

Этот метод является операцией O (1).

Ссылка

Просто, чтобы расширить ответ JaredPar. По его словам, возвращение фактического поля поддержки не является полностью безопасным, поскольку пользователь все еще может динамически преобразовывать IEnumerable обратно в ArrayList .

Я бы написал что-то вроде этого, чтобы убедиться, что в исходный список не внесено никаких изменений:

public IEnumerable MyList
{
    get
    {
         foreach (object o in mMyList)
             yield return o;
    }
}

Опять же, я бы, вероятно, также использовал общий список ( IEnumerable < T > ) для обеспечения полной безопасности типов.

Используйте ReadOnlyCollection .

  

возвращает новый объект ReadOnlyCollection < object > (mMyList) .

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

Если вы знаете, что mMyList содержит только один тип объекта (например, он не имеет ничего, кроме DateTimes), Вы можете вернуть ReadOnlyCollection < DateTime > (или некоторый другой тип) для обеспечения дополнительной безопасности типов. Если вы используете C # 3, вы можете просто написать

  

возвращает новую коллекцию ReadOnlyCollection < DateTime > (mMyList.OfType < DateTime > (). ToArray ())

Тем не менее, это не будет автоматически обновляться с базовым списком, а также будет менее эффективным (он скопирует весь список). Лучший вариант - сделать mMyList общим List < T > (например, List < DateTime > )

Вы должны поместить возвращаемое значение в коллекцию только для чтения.

Доступно в .NET v2.0

    public ArrayList MyList { get; private set; }

Просто сделайте свойство как Sealed (или NotInheritable в VB.NET) и только для чтения, например, так:

   public sealed readonly ArrayList MyList
   {
       get { return mMyList;}
   }

Также не забудьте сделать вспомогательное поле доступным только для чтения:

   private readonly ArrayList mMyList;

Но чтобы инициализировать значение mMyList, вы должны инициализировать его ТОЛЬКО в конструкторе, как в этом примере:

public SampleClass()
{
   // Initialize mMyList
   mMyList = new ArrayList();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top