Только для чтения "Accessor Access" в С#
У меня есть следующий класс:
class SampleClass
{
private ArrayList mMyList;
SampleClass()
{
// Initialize mMyList
}
public ArrayList MyList
{
get { return mMyList;}
}
}
Я хочу, чтобы пользователи могли получать mMyList, поэтому я разоблачил "get" через свойство, но я не хочу, чтобы изменения, которые они вносили в объект (например, MyList.Add(новый класс());) чтобы вернуться в мой класс.
Я думаю, я могу вернуть копию объекта, но это может быть медленным, и я ищу способ, который предоставит ошибку времени компиляции, информируя пользователя о том, что они не должны ожидать, что смогут изменить возвращенный значение из свойства.
Возможно ли это?
Ответы
Ответ 1
С помощью ArrayList вы достаточно ограничены, потому что в BCL нет только обычного класса коллекций. Быстрое и грязное решение - вернуть тип IEnumerable.
public IEnumerable MyList
{
get { return mMyList;}
}
Это фактически не позволит кому-то отдать в ArrayList, но по умолчанию он не разрешит изменения
Вы можете вернуть эффективный список только для чтения, вызвав ArrayList.ReadOnly. Однако возвращаемый тип - это ArrayList, поэтому пользователь все равно сможет скомпилировать с .Add, но это приведет к ошибке выполнения.
Ответ 2
Используйте метод ArrayList.ReadOnly() для создания и возврата обертки только для чтения в списке. он не будет копировать список, а просто создаст обходную оболочку только для чтения. Чтобы получить проверку времени компиляции, вы, вероятно, захотите вернуть обертку только для чтения, как IEnumerable, как предлагает @Jared.
public IEnumerable MyList
{
get { return ArrayList.ReadOnly(mMyList); }
}
Коллекция, доступная только для чтения, просто коллекция с оберткой что предотвращает коллекция. Если изменения внесены в базовая коллекция, только для чтения коллекция отражает эти изменения.
Этот метод является операцией O (1).
Ссылка
Ответ 3
Просто для продолжения ответа JaredPar. По его словам, возвращение фактического поля поддержки не является полностью безопасным, так как пользователь все еще способен динамически отбрасывать IEnumerable
обратно на ArrayList
.
Я бы написал что-то вроде этого, чтобы не было никаких изменений в исходном списке:
public IEnumerable MyList
{
get
{
foreach (object o in mMyList)
yield return o;
}
}
Тогда, опять же, я бы предположительно использовал общий список (IEnumerable<T>
), чтобы быть полностью безопасным.
Ответ 4
Используйте ReadOnlyCollection
.
return new ReadOnlyCollection<object>(mMyList)
.
Вы также можете сделать поле ReadOnlyCollection
a, и оно автоматически отразит изменения в базовом списке. Это наиболее эффективное решение.
Если вы знаете, что mMyList содержит только один тип объекта (например, он не имеет ничего, кроме DateTimes)
вы можете вернуть ReadOnlyCollection<DateTime>
(или какой-либо другой тип) для дополнительной безопасности типа. Если вы используете С# 3, вы можете просто написать
return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())
Однако это не будет автоматически обновляться в базовом списке, а также менее эффективно (он скопирует весь список). Лучший вариант - сделать mMyList общим List<T>
(например, a List<DateTime>
)
Ответ 5
Список (T). Метод AsReadOnly =)
Ответ 6
Вы должны обернуть возвращаемое значение в коллекции только для чтения.
Ответ 7
Доступно из .NET v2.0
public ArrayList MyList { get; private set; }
Ответ 8
Просто сделайте свойство Sealed (или NotInheritable в VB.NET) и readonly, как это:
public sealed readonly ArrayList MyList
{
get { return mMyList;}
}
Также не забудьте сделать поле поддержки как только для чтения:
private readonly ArrayList mMyList;
Но для инициализации значения mMyList вы должны инициализировать его ТОЛЬКО в конструкторе, как в этом примере:
public SampleClass()
{
// Initialize mMyList
mMyList = new ArrayList();
}