Правильное использование свойств С# - программирование
Подтвердить что ты не робот

Правильное использование свойств С#

private List<Date> _dates;

public List<Date> Dates
{
    get { return _dates; }
    set { _dates = value; }
}

ИЛИ

public List<Date> Dates
{
    get;        
    set;    
}

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

Возможно ли, что использование первого параметра приведет к созданию дополнительного объекта List<Date>, а затем заменяется все _dates на value или он более интеллектуальный, чем этот?

Кроме того, что является самым заметным в отрасли или это полностью субъективно?

4b9b3361

Ответ 1

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

С точки зрения эффективности кода они также эквивалентны, компилятор только вовремя обычно обращается к частной переменной без накладных расходов на вызов функции доступа (после того, как среда выполнения проверила доступность и т.д.).

С точки зрения кодирования, я предпочитаю вторую версию, которая более компактна (меньше для записи, меньше для чтения).

Второй синтаксис был введен в С# 3.0. Таким образом, первый вариант будет более совместим со старыми компиляторами.

Ответ 2

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

Используйте последнее в противном случае. Это делает вещи намного чище. Вы также можете использовать свойства только для чтения, используя автоматические свойства:

public List<Date> Dates { get; private set; }

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

private List<Date> _dates = new List<Date>();
private ReadOnlyCollection<Date> _readOnlyDates =
    new ReadOnlyCollection<Date>(_dates);

public ReadOnlyCollection<Date> Dates
{
    get { return _readOnlyDates; }
}

Ответ 3

Оба они в основном одинаковы из-за того, как .NET компилирует автоматические свойства. Автоматические свойства стали доступны в .NET 3.5.

Ответ 4

Я предпочитаю использовать свойства auto больше, потому что свойство является хорошим способом выразить намерение о том, что делает ваш объект, но все еще имеет некоторую защиту.

Почти все мои объявления свойств выглядят так:

public bool IsBlah { get; private set; }

Это делает его приятным, читаемым и защищенным получателем.

Но есть моменты, когда требуется явное поле поддержки:

private bool? _isBlah;
public bool IsBlah
{
    get
    {
        if (_isBlah == null)
        {
            // Do something expensive here and set _isBlah
            _isBlah = true;
        }
        return _isBlah;
    }
}

Ответ 5

Первый - это оригинальный подход, последний - пример более нового объекта "auto properties", благодаря которому компилятор автоматически создает для вас поле поддержки.

Некоторые люди (включая меня) уклоняются от свойств auto, потому что синтаксис легко ошибочно воспринимается для абстрактных свойств, нет возможности для свойств "readonly", а синтаксис для свойств auto с частными сеттерами неудобен:

public List Dates
{
    get;
    private set;
}

Мне также неудобно иметь внутренние поля доступа к классам через API классов.

Ответ 6

Вторая вариация известна как автоматически реализованные свойства и была введена в С# 3.0 (следовательно, почему вы, возможно, не столкнулись с ней раньше).

Предпочтительно использовать этот формат, если вы хотите создавать простые свойства с помощью полей поддержки и не нуждаетесь в реализации какой-либо логики в "getter" и "setter". Мало того, что он более краткий, но он также заставляет вас напрямую обращаться к собственности, а не проходить через поле поддержки, которое обычно является наилучшей практикой.

Обратите внимание, что вы все еще можете инициализировать свойства, вы просто делаете это через конструктор.

public class MyClass
{

  public List<Date> Dates
  {
      get;        
      set;    
  }

  public MyClass()
  {
      Dates = new List<Date>();
  }

}

Ответ 7

Я лично предпочитаю первый метод, так как он позволяет выполнить несколько операций до возврата.

например. (Очень плохой пример)

    private int _limit;
    private int _onHand;
    private bool returnToVendor;

    public Item(int limit, int onHand)
    {
       _limit = limit;
       _onHand = onHand;
    }

    public int ReturnStock
    {
       get
       {
         if(_onHand > _limit)
         {
            returnToVendor = true;
            return _onHand;
         }
       }

       set
       {
           _onHand = value;

           if(_onHand < _limit)
           {
              returnToVendor = false;
           }
       }
    }

Ответ 8

Это не имеет значения. Второй - просто сахар. Я всегда использую второй, потому что он чище, но каждый раз в то время мне нужен доступ к значению резервного копирования.

Ответ 9

Пока вам не нужно проверять, что List<Date> инициализирован в getter, вы в порядке с обеими версиями. Я просто предлагаю вам использовать одну версию, и вы не смешиваете ее в своем коде...

Если вам нужно его инициализировать, вам нужно перейти к первой версии...

private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { if (_dates == null) _dates = new List<Date>(); return _dates; } 
    set { _dates = value; } 
} 

Ответ 10

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

Ответ 11

Оба скомпилированы примерно одинаково (я не знаю, что имя поля поддержки было бы точно таким же, но они были бы функционально эквивалентны).

IIRC, возможность делать автоматические свойства (public List<Date> Dates {get; set;}) была добавлена ​​либо в .NET 3.0, либо в 3.5.

Ответ 12

Насколько я помню, я всегда управлял своими свойствами списка из моего объекта, делая их только для чтения.

private IList<DateTime> _dates;

public MyClass() {
    _dates = new List<DateTime>();
}

public IList<DateTime> Dates {
    get {
        return _dates;
    }
}

Таким образом, я заверяю, что мой список никогда не имеет значения null, когда я обращаюсь к нему, поскольку клиент не может его назначить.

Однако для вашего примера вам нужно использовать только прежний подход, если вам нужна какая-то логика при получении или установке свойства. В противном случае автоматические свойства будут делать то же самое, что и вы, только получая и устанавливая значение для частного поля. Кроме того, { get; set; } улучшает читаемость и помогает другим программистам понять ваше намерение в моей скромной точке зрения.

Например:

public class MyClass {
    private IList<DateTime> _dates;

    public IList<DateTime> Dates {
        get {
            return _dates;
        } set {
            _dates = value;
        } 
    }
}

против

public class MyClasse {
    public IList<DateTime> Dates { get; set; }
}

Второй способ делает его более компактным и быстрым, по крайней мере, для меня, каково намерение. И становится быстрее кодировать класс, когда нет никакой логики внутри геттера и сеттера.

В противном случае, один не лучше другого и делает то же самое, говоря о получении и настройке просто значения свойства без логики.

Самое главное, вам нужно быть в курсе вашего кода. Если это закончится тем, что вы не получаете никаких улучшений, и вам нравится то, что вы делаете, чем просто делать это. =)