Правильное использование свойств C # - PullRequest
13 голосов
/ 20 августа 2010
private List<Date> _dates;

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

OR

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

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

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

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

Ответы [ 12 ]

19 голосов
/ 20 августа 2010

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

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

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; }
}
7 голосов
/ 20 августа 2010

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

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

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

7 голосов
/ 20 августа 2010

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

4 голосов
/ 20 августа 2010

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

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

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;
    }
}
1 голос
/ 20 августа 2010

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

например. (Действительно плохой пример)

    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;
           }
       }
    }
1 голос
/ 20 августа 2010

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

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

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

public class MyClass
{

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

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

}
1 голос
/ 20 августа 2010

Первый - это оригинальный подход, второй - пример более новой функции «автоматических свойств», при которой компилятор автоматически создает для вас вспомогательное поле.

Некоторые люди (включая меня) избегают автоматических свойств, потому что синтаксис легко ошибочно принять за абстрактные свойства, нет возможности для свойств «только для чтения», а синтаксис для автоматических свойств с частными установщиками неуклюж

public List Dates
{
    get;
    private set;
}

Мне также неудобно, когда внутренняя реализация моих классов обращается к полям через API класса.

0 голосов
/ 20 августа 2010

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

private IList<DateTime> _dates;

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

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

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

Однако, для вашего примера вам нужно использовать первый подход, только если вам нужна какая-то логика при получении или установке свойства. В противном случае автоматические свойства работают точно так же, как если бы вы получали и устанавливали значение для частного поля. Более того, { 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; }
}

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

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

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

0 голосов
/ 20 августа 2010

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

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

0 голосов
/ 20 августа 2010

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

...