Элемент маркировки С# как "не использовать"
public class Demo
{
private List<string> _items;
private List<string> Items
{
get
{
if (_items == null)
_items = ExpensiveOperation();
return _items;
}
}
}
Другие методы класса Demo
будут иметь доступ к полю _items
. Поскольку я использую свойство для ленивой загрузки элементов, я не хочу, чтобы другой разработчик ошибочно пытался использовать поле _items
.
Я знаю, что есть ObsoleteAttribute, который я могу использовать, но это поле технически не устарело.
Есть ли лучший способ отметить член как "не использовать"?
Ответы
Ответ 1
Хотя это не общий метод для того, что вы хотите сделать (и нет никого, и, как будут затронуты другие ответы, вам нужно доверять другим разработчикам), в этом случае вы могли бы создать Lazy<List<T>>
( предполагая, что .NET 4 или более поздняя версия - хотя это легко для резервного копирования)
class Demo {
readonly Lazy<List<string>> _items;
public Demo() {
var _items = new Lazy<List<string>>( ExpensiveOperation);
}
List<string> Items { get { return _items.Value; }}
}
Подход readonly
/non-mutable, как правило, подходит для поддержки полей в обоих направлениях.
EDIT: на основе ответа @Timwi (пойдите +1, если вам нравится идея), можно пойти в город на нем, а в стиле JavaScript используйте возможность на основе ограничений, чтобы даже не разоблачить поле Lazy
, просто операция, закрытая над ним (также включает предложение @Mr Disappointment ReadOnlyCollection
):
class Demo {
readonly Func<ReadOnlyCollection<string>> _getItems;
public Demo() {
var items = new Lazy<List<string>>( ExpensiveOperation);
_getItems = () => items.Value.AsReadOnly();
}
ReadOnlyCollection<string> Items { get { return _getItems(); }}
}
И, таким образом, заканчивается наше глупое сообщение о трюках.
Ответ 2
Переименуйте поле _items
в _heyFutureDeveloperDoNotReferenceThisFieldMmmkay
Ответ 3
Если вы установили такой атрибут, то как бы gett Items
получить доступ к нему без создания того же предупреждения/ошибки, которое создало бы то, что вы искали?
Что вы подразумеваете под "другим разработчиком"? Если вы имеете в виду другого разработчика, работающего над этим же кодом (с вами), то простой комментарий вроде:
///<summary>Do not access directly, using lazy initialization in getter.</summary>
должно быть достаточно, поскольку Visual Studio покажет, что всякий раз, когда он зависает над полем.
Если вы имеете в виду кого-то, кто использует этот класс, то это весь смысл скрытия информации, и вам хорошо идти.
Ответ 4
Да, есть относительно простой способ. Некоторые могут подумать об этом как о взломе, но я думаю, что это законно. Он использует правила определения локальной переменной для достижения желаемой конфиденциальности на уровне метода:
public class Demo
{
private readonly Func<List<string>> _getItems;
public Demo()
{
List<string> items = null;
_getItems = () =>
{
if (items == null)
items = ExpensiveOperation();
return items;
};
}
public List<string> Items { get { return _getItems(); } }
}
Теперь переменная items
правильно привязана к методу, который ее использует. Доступ к _getItems
по-прежнему возможен, но это несущественно, потому что оно делает то же самое, что и items
. Невозможно изменить items
, поскольку он является локальным или _getItems
, потому что он доступен только для чтения.
Ответ 5
Я считаю, что это очень важная вещь, которую нужно делать. К сожалению, С# не был разработан с учетом этого. Таким образом, на самом деле вы не можете реально сделать это на практике в текущей версии языка.
Если вы не доверяете разработчикам своей команды, у вас больше проблем, о которых можно беспокоиться.
Сильное несогласие; если вы доверяете любому, даже самому себе, то есть когда у вас есть проблема. Лучший код никому не доверяет. Лучший код - пуленепробиваемый. Он не оставляет никоим образом для всех, кто может испортить.
С# не делает этого возможным, хотя он подходит ближе, чем многие другие языки.
Это личное. Бак останавливается. Если более чем один разработчик работает в частных частях класса, тогда они должны хорошо общаться.
В принципе тот же аргумент. Да, это личное, но так что? Почему это не является правильной вещью, чтобы хотеть инкапсулировать частные детали хорошо?
P.S. Я предложил связанный (но не совсем соответствующий) практический подход, чтобы обеспечить лучшую проверку кода на С#, но я не думаю многие видели это. Итак, здесь идет:) Я бы хотел увидеть практический подход к инкапсуляции частных членов.
Ответ 6
Ничего не делать.
С публичным или защищенным членом хорошо написанного класса мы ожидаем, что он будет работать с ним разумно, и случай, когда это не так, должно быть хорошо документировано.
С частным полем нет причин, по которым мы будем делать такое предположение.
Кроме того, если я прихожу к этому классу в качестве нового разработчика в команде, я не знаю, что делает _items
. Что я буду с этим делать? Нет никакой важной работы, которую я могу сделать, пока не посмотрю, что с ней делает существующий код. И я увижу, что это резервное поле для ленивого загруженного имущества. Тем более, если есть даже небольшой фрагмент документальных комментариев.
Не похоже, что вы можете просто произвольно делать все, что хотите, с другими частными полями и ожидать, что он будет работать.
Ответ 7
Как насчет
private Dictionary<String,Object> PandorasCoochie = new Dictionary<String,Object>()
Затем разместите там своих неприкосновенных носителей.