Есть ли причины использовать частные свойства в C #? - PullRequest
211 голосов
/ 22 июля 2010

Я только что понял, что конструкцию свойства C # можно также использовать с модификатором доступа private :

private string Password { get; set; }

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

private string _password;

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

private string Password { get; }

или

private string Password { set; }

, но, возможно, есть сценарий использования с вложенными / унаследованными классами или, возможно, где get / set может содержать логика вместо простого возврата значения свойства, хотя я будет стремиться сохранять свойства строго простыми и позволять явным методам выполнять любую логику, например GetEncodedPassword().

Кто-нибудь использует частные свойства в C # по какой-либо причине, или это только одна из тех технически возможных, но редко используемых в фактическом коде конструкций?

Добавление

Хорошие ответы, прочитав их, я выбрал следующие варианты использования частных объектов:

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

Ответы [ 16 ]

189 голосов
/ 22 июля 2010

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

private string _password;
private string Password
{
    get
    {
        if (_password == null)
        {
            _password = CallExpensiveOperation();
        }

        return _password;
    }
}
123 голосов
/ 22 июля 2010

Основное использование этого в моем коде - ленивая инициализация, как уже упоминали другие.

Другая причина использования частных свойств над полями состоит в том, что частные свойства гораздо, гораздо проще отлаживать, чем частные поля. Я часто хочу знать такие вещи, как «это поле неожиданно устанавливается; кто первый, кто устанавливает это поле?» и это намного проще, если вы можете просто поставить точку останова на сеттере и нажать кнопку go. Вы можете поставить вход в систему там. Вы можете поместить показатели производительности там. Вы можете включить проверки согласованности, которые выполняются в отладочной сборке.

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

40 голосов
/ 22 июля 2010

возможно, есть сценарий использования с вложенными / унаследованными классами или, возможно, где get / set может содержать логику, а не просто возвращать значение свойства

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

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


В полусвязанном случае (хотя и отличающемся от вашего вопроса) я очень часто использую частные сеттеры для открытых свойств:

public string Password 
{
    get; 
    private set;
}

Это дает вам общедоступный метод получения, но сохраняет его в частном порядке.

20 голосов
/ 22 июля 2010

Ленивая инициализация - это одно место, где они могут быть аккуратными, например,

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);

private MyType MyType { get { return this.mytype.Value; } }

// In C#6, you replace the last line with: private MyType MyType => myType.Value;

Тогда вы можете написать: this.MyType везде, а не this.mytype.Value и инкапсулировать тот факт, что он лениво создается в одном месте.

Обидно то, что C # не поддерживает определение области поддержки для свойства (т. Е. Объявляет его внутри определения свойства), чтобы полностью скрыть его и обеспечить доступ к нему только через свойство. *

18 голосов
/ 22 июля 2010

Одно хорошее использование для частных свойств get only - это расчетные значения.Несколько раз у меня были свойства, которые доступны только для чтения и просто делали вычисления над другими полями в моем типе.Он не достоин метода и не интересен другим классам, поэтому это частная собственность.

12 голосов
/ 22 июля 2010

Единственное использование, которое я могу вспомнить

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}
10 голосов
/ 22 июля 2010

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

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

8 голосов
/ 22 июля 2010

Я использую их в сериализации с такими вещами, как DataContractSerializer или protobuf-net, которые поддерживают это использование (XmlSerializer не поддерживает). Это полезно, если вам нужно упростить объект как часть сериализации:

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}
6 голосов
/ 22 июля 2010

Одна вещь, которую я делаю все время, - это сохранение "глобальных" переменных / кэша в HttpContext.Current

private static string SomeValue{
  get{
    if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
      HttpContext.Current.Items["MyClass:SomeValue"]="";
    }
    return HttpContext.Current.Items["MyClass:SomeValue"];
  }
  set{
    HttpContext.Current.Items["MyClass:SomeValue"]=value;
  }
}
5 голосов
/ 03 декабря 2014

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

    private double MonitorResolution
    {
        get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
    }

Это полезно, если есть много под-свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...