Подтвердить что ты не робот

Элемент маркировки С# как "не использовать"

public class Demo
{
    private List<string> _items;
    private List<string> Items
    {
        get
        {
            if (_items == null)
                _items = ExpensiveOperation();

            return _items;
        }
    }
}

Другие методы класса Demo будут иметь доступ к полю _items. Поскольку я использую свойство для ленивой загрузки элементов, я не хочу, чтобы другой разработчик ошибочно пытался использовать поле _items.

Я знаю, что есть ObsoleteAttribute, который я могу использовать, но это поле технически не устарело.

Есть ли лучший способ отметить член как "не использовать"?

4b9b3361

Ответ 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>()

Затем разместите там своих неприкосновенных носителей.