Как я могу получить доступ к резервной переменной автоматически реализуемого свойства?

79

Раньше мы декларировали такие свойства:

public class MyClass
{
    private int _age;

    public int Age
    {
          get{ return _age;  }
          set{ _age = value; }
    }
}

Теперь мы можем:

public class MyClass
{
    public int Age {get; set;} 
}

Мой вопрос: как мне получить доступ к частной переменной, которая создается автоматически с использованием этой нотации?

Я бы предпочел использовать частную переменную, а не общедоступный метод доступа Age. Есть ли запись по умолчанию для доступа к частной переменной, или это просто невозможно?

публичная статика
источник
10
В чем разница в этом случае доступа к частному и общедоступному аксессору? Я думаю, что лучше всего получить доступ к общедоступному аксессору даже из логики в объявляющем классе. Если вы когда-нибудь добавите логику в средство доступа, вам не захочется менять весь свой код.
Эрик Шуновер,
@ Spok16 Можете ли вы привести мне пример добавления логики к аксессору и необходимости в результате изменить весь ваш код. Я не совсем понял эту часть.
Ogen

Ответы:

92

Цель новых автоматических свойств - уменьшить объем шаблонного кода, который вам нужно написать, когда у вас есть простое свойство, которое не требует специальной логики в получении или наборе.

Если вы хотите получить доступ к закрытому члену, который используют эти свойства, обычно это происходит по нескольким причинам:

  • Вам нужно больше, чем просто получить / установить - в этом случае вам следует просто избегать использования автоматических свойств для этого члена.
  • Вы хотите избежать снижения производительности при прохождении get или set и просто использовать член напрямую - в этом случае я был бы удивлен, если бы действительно был удар производительности. Простые члены get / set очень легко встроить, и в моем (по общему признанию ограниченном) тестировании я не нашел разницы между использованием автоматических свойств и прямым доступом к члену.
  • Вам нужен только публичный доступ для чтения (т.е. просто «получить»), а класс записывает элемент напрямую - в этом случае вы можете использовать частный набор в своем автоматическом свойстве. т.е.

    public class MyClass
    {
        public int Age {get; private set;} 
    }

Обычно это покрывает большинство причин, по которым нужно напрямую перейти к вспомогательному полю, используемому автоматическими свойствами.

Wilka
источник
Верно - они сокращают код боулерплейта, и я также сообщу, что они сокращают то, что вам нужно тестировать. Кто-то может возразить, что вам нужно тестировать получение / установку вручную, но не с автоматическими свойствами, поскольку вы можете доверять фреймворку.
Дэниел Аугер,
3
Образец кода здесь неверен. Это должен быть открытый класс MyClass {public int Age {get; private set;}} Я согласен с этим ответом. Вы не можете получить доступ к частному полю, и если вам нужно, то вам вообще не следует использовать автоматические свойства.
hwiechers
hwiechers, спасибо за это - у меня было это редактирование, но при попытке исправить форматирование я, должно быть, снова нажал пасту и удалил неправильный блок кода. Дох!
Wilka,
Обычно используется в объектах POCO
RobS
23

Использование автоматических свойств подразумевает, что вам не нужна никакая логика получения / настройки для свойства, поэтому частная поддерживающая переменная не нужна.

Не используйте автоматические свойства, если в вашем классе есть сложная логика. Просто используйте private int _ageобычные геттеры / сеттеры, как обычно.

ИМО, автоматические свойства больше подходят для быстрой реализации одноразовых объектов или временных капсул данных, таких как:

public class TempMessage {
    public int FromID { get; set; }
    public int ToID { get; set; }
    public string Message { get; set; }
}

Где не нужно много логики.

чакрит
источник
Почему добавление сложной логики к вашему классу повлияет на то, используете ли вы автоматические свойства в этом классе?
Эрик Шуновер,
Больше согласованности ... если у вас сложная логика, вы захотите получить к ней доступ из частной резервной переменной в соответствии с практиками OO ... и если вы используете автоматические свойства, тогда ... будут несоответствия в доступе к этим свойствам . поскольку некоторые будут иметь префикс подчеркивания, а некоторые нет.
chakrit
12

Этот синтаксис обычно называют «синтаксическим сахаром», что означает, что компилятор берет этот синтаксис и переводит его во что-то другое. В вашем примере компилятор сгенерирует код, который выглядит примерно так:

[CompilerGenerated]
private int <Age>k_BackingField;

public int Age
{
   [CompilerGenerated]
   get
   {
      return this.<Age>k_BackingField;
   }
   [CompilerGenerated]
   set
   {
      this.<Age>k_BackingField = value;
   }

Даже зная все это, вы, вероятно, могли бы получить доступ к резервному полю напрямую, но такого рода поражение цели использования автоматических свойств. Я говорю, вероятно, здесь, потому что тогда вы зависите от деталей реализации, которые могут измениться в любой момент в будущей версии компилятора C #.

Скотт Дорман
источник
10

За кулисами происходит внедрение частной переменной-члена с префиксом <> k__AutomaticallyGeneratedPropertyField #

Из C # 3.0 объяснение автоматических свойств

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

макбирди
источник
7

Не стоит, да и вряд ли понадобится. Если вам нужно получить доступ к свойству, просто используйте общедоступное свойство (например, this.Age). Нет ничего особенного в частном поле, поддерживающем общественную собственность, использование его вместо собственности - просто суеверие.

Клин
источник
1
Мне всегда было интересно, в чем смысл автоматических свойств. Если у вас нет специальной логики в ваших геттерах и сеттерах, зачем они вообще?
Мэтью Лок
4
@MatthewLock гибкость. С прямым доступом к полям вы заблокированы в этом дизайне, если вы не измените весь клиентский код одновременно. Но со свойством, если вы решите изменить его из «псевдополя» на вычисляемое свойство, или если вы решите добавить утверждения и проверки для установщика, или что-то еще, вы можете сделать это прозрачно. Это даже более полезно, если вы пишете код библиотеки, в котором вы не можете контролировать весь клиентский код.
Wedge
2

Вы не можете, это языковая функция, а не функция IDE. Честно говоря, я бы предпочел, чтобы IDE добавила для вас частную переменную. Я согласен с тем, что для класса немного странно внутренне использовать публичную точку входа для доступа к своим собственным переменным. Следовательно, я сам не так часто использую эту новую функцию.

Придирчивый
источник