Есть ли причины использовать частные объекты в С#?

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

private string Password { get; set; }

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

private string _password;

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

private string Password { get; }

или

private string Password { set; }

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

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

Добавление

Хорошие ответы, чтение через них Я отбраковал эти использования для частных свойств:

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

Ответ 1

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

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

        return _password;
    }
}

Ответ 2

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

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

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

Ответ 3

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

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

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


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

public string Password 
{
    get; 
    private set;
}

Это дает вам публичный getter, но сохраняет setter private.

Ответ 4

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

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, и инкапсулировать тот факт, что он лениво создается в одном месте.

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

Ответ 5

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

Ответ 6

Единственное, что я могу думать о

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}

Ответ 7

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

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

Ответ 8

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

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}

Ответ 9

Одна вещь, которую я делаю все время, - это хранить "глобальные" переменные/кеш в 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;
  }
}

Ответ 10

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

Также может быть полезно, если вам потом придется каким-то образом изменить тип данных или если вам нужно использовать отражение.

Ответ 11

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

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

Полезно, если есть много дополнительных свойств.

Ответ 12

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

Ответ 13

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

Если это просто поле прямой поддержки? Ничто не приходит на ум в качестве веской причины.

Ответ 14

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

  • Проверка

    string _password;
    string Password
    {
        get { return _password; }
        set
        {
            // Validation logic.
            if (value.Length < 8)
            {
                throw new Exception("Password too short!");
            }
    
            _password = value;
        }
    }
    
  • Блокировка

    object _lock = new object();
    object _lockedReference;
    object LockedReference
    { 
        get
        {
            lock (_lock)
            {
                return _lockedReference;
            }
        }
        set
        {
            lock (_lock)
            {
                _lockedReference = value;
            }
        }
    }
    

    Примечание. При блокировке ссылки вы не блокируете доступ к элементам ссылочного объекта.

Ленивая ссылка: При отложенной загрузке вам может понадобиться сделать это асинхронно, для чего в настоящее время существует AsyncLazy. Если вы используете более старые версии, чем Visual Studio SDK 2015, или не используете его, вы также можете использовать AsyncEx AsyncLazy.

Ответ 15

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

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

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

Кроме того, Visual Studio Professional будет предоставлять информацию о свойстве, а не поле, чтобы было легче увидеть, какое поле используется.

PorpField

Ответ 16

Некоторые более экзотические использования явных полей включают в себя:

  • вам нужно использовать ref или out со значением - возможно, потому что это счетчик Interlocked
  • он предназначен для представления фундаментального макета, например, в struct с явным макетом (возможно, для сопоставления с дампом C++ или unsafe кодом)
  • исторически этот тип использовался с BinaryFormatter с автоматической обработкой полей (изменение на auto-props изменяет имена и, таким образом, разрушает сериализатор)