Поскольку я обычно возвращаю только неизменяемые (неизменяемые) объекты из свойств / методов, этот ответ предполагает, что вы хотите сделать то же самое.
Не забудьте о ReadOnlyCollection<T>
, который возвращает неизменную коллекцию, которая все еще можетбыть доступным по индексу.
Если вы используете IEnumerable<T>
и выпускаете свой тип в неконтролируемую пустыню, будьте осторожны с этим:
class MyClass {
private List<int> _list;
public IEnumerable<int> Numbers {
get { return _list; }
}
}
Как пользователь может сделать это и запутатьсяup внутреннее состояние вашего класса:
var list = (List<int>)myClass.Numbers;
list.Add(123);
Это нарушит намерение только для чтения для свойства.В таких случаях ваш геттер должен выглядеть следующим образом:
public IEnumerable<int> Numbers {
get { return new ReadOnlyCollection<int>(_list); }
}
В качестве альтернативы вы можете позвонить _list.ToReadOnly()
.Я написал это полностью, чтобы показать тип.
Это остановит любого, кто изменяет ваше состояние (если они не используют отражение, но это действительно трудно остановить, если вы не создадите неизменные коллекции, подобные тем, которые используются во многих функциональных языках программирования,и это совсем другая история).
Если вы возвращаете коллекции только для чтения, вам лучше объявить участника как ReadOnlyCollection<T>
, так как тогда некоторые действия выполняются быстрее (подсчет, доступ к элементам по индексу,копирование в другую коллекцию).
Лично я хотел бы, чтобы инфраструктура включала и использовала такой интерфейс:
public interface IReadOnlyCollection<T> : IEnumerable<T>
{
T this[int index] { get; }
int Count { get; }
bool Contains(T item);
void CopyTo(T[] array, int arrayIndex);
int IndexOf(T item);
}
Вы можете получить все эти функции, используя методы расширения поверхIEnumerable<T>
но они не такие совершенные.