Можете ли вы позволить вызывающей стороне изменять внутренний массив через свойство?Да, конечно, но вы возьмете на себя множество возможных проблем.Как вы справляетесь с этими проблемами и с чем вы можете жить, зависит только от вас.
Рекомендации MSDN верны в очень строгом смысле.Тем не менее, я видел свойства List<T>
и T[]
, возвращенные ранее из классов.Если ваш класс очень простой POCO, это не является большой проблемой, потому что тогда эти классы являются просто необработанными данными, и на них нет реальной бизнес-логики.
Тем не менее, если я возвращаю список, иЯ не хочу, чтобы кто-то связывался с внутренним списком, я либо каждый раз возвращаю глубокую копию, либо ReadOnlyCollection
, либо итератор.Например, есть много мест, где я кеширую вызовы запросов веб-службы, и когда я возвращаю элемент кеша, я НЕ хочу, чтобы вызывающий абонент изменял эти данные, иначе они изменят то, что я кеширую.Таким образом, там я делаю глубокие копии (что все же быстрее, чем издержки вызова веб-службы).
Вам просто нужно знать, требует ли ваше использование безопасность или нет.Класс только для внутреннего потребления?Или он предназначен для более широкой аудитории, и вы не представляете, что они собираются с ним делать?Этот тип вопросов может стимулировать ваш ответ.
Извините за ответ "все зависит", но он действительно зависит от вашей цели и от того, насколько внутреннее устройство класса чувствительно к изменениям.
ОБНОВЛЕНИЕ Вы также можете вернуть итератор, я бы не стал возвращать IEnumerable в качестве приведения суперкласса, поскольку он может быть приведен обратно, но если вместо этого вы возвращаете итератор (например, с помощью Skip (0)) вы в безопасности (если не считать возможности изменять содержащиеся объекты, конечно).
Например:
public IEnumerable<T> SomeList
{
get { return _internalList.Skip(0); }
}
Лучше, чем:
public IEnumerable<T> SomeList
{
get { return _internalList; }
}
Потому что последний может быть возвращен к List<T>
или к чему-то еще, тогда как первый является итератором и не может быть изменен.