Я просто понял, что конструкция свойства C# может также использоваться с частным модификатором доступа:
private string Password { get; set; }
Хотя это технически интересно, я не могу вообразить, когда я использовал бы его, так как частное поле включает еще меньше церемонии:
private string _password;
и я не могу вообразить, когда я должен был бы когда-либо мочь внутренне получить, но не установить или установить, но не получить частное поле:
private string Password { get; }
или
private string Password { set; }
но возможно существует вариант использования с вложенным / наследованные классы или возможно где получение/устанавливание могло бы содержать логику вместо того, чтобы просто отдать значение свойства, хотя я буду склонен сохранять свойства строго простыми и позволять явным методам сделать любую логику, например. GetEncodedPassword()
.
Кто-либо использует частные собственности в C# по какой-либо причине или является этим только одна из тех конструкций technically-possible-yet-rarely-used-in-actual-code?
Хорошие ответы, прочитывая их я отобрал это использование для частных собственностей:
Я использую их, если мне нужно кэшировать значение и я хочу отложить его загрузку.
private string _password;
private string Password
{
get
{
if (_password == null)
{
_password = CallExpensiveOperation();
}
return _password;
}
}
Одна вещь, которую я делаю все время, это хранение "глобальных" переменных/кэша в 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;
}
}
Это имеет смысл, когда есть логика, связанная с набором свойств или получением (подумайте о ленивой инициализации), и свойство используется в нескольких местах в классе.
Если это просто прямое защитное поле? Ничего не приходит в голову как веская причина.
Обычной практикой является изменение членов только с помощью методов get/set, даже приватных. Логика заключается в том, что вы знаете, что ваши get/set всегда ведут себя определенным образом (например, вызывают события), что кажется бессмысленным, поскольку они не будут включены в схему свойств... но старые привычки умирают с трудом.
Я использую их то и дело. Они могут упростить отладку, если вы можете легко установить точку останова в свойстве или добавить оператор регистрации и т. Д.
Также могут быть полезны, если вам позже потребуется каким-то образом изменить тип ваших данных или если вам нужно использовать отражение.
Свойства и поля не однозначны. Свойство относится к интерфейсу класса (будь то открытый или внутренний интерфейс), а поле - о реализации класса. Свойства не следует рассматривать как способ просто раскрыть поля, их следует рассматривать как способ раскрыть намерение и цель класса.
Точно так же, как вы используете свойства, чтобы представить своим потребителям контракт о том, что составляет ваш класс, вы также можете представить контракт себе по очень похожим причинам. Так что да, я использую частные свойства, когда это имеет смысл. Иногда частное свойство может скрыть детали реализации, такие как отложенная загрузка, тот факт, что свойство действительно представляет собой совокупность нескольких полей и аспектов или что свойство необходимо виртуально создавать при каждом вызове (подумайте DateTime.Now
]). Определенно бывают случаи, когда имеет смысл принудить это даже к себе в бэкэнде класса.
Единственное применение, о котором я могу думать
private bool IsPasswordSet
{
get
{
return !String.IsNullOrEmpty(_password);
}
}
Одно из хороших применений для свойств private get only - это вычисляемые значения. Несколько раз у меня были свойства, которые были приватными readonly и просто выполняли вычисления над другими полями моего типа. Это недостойно метода и не интересно другим классам, поэтому это частное свойство.
Ленивая инициализация - одно из мест, где они могут быть аккуратными, например,
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# не поддерживает привязку опорного поля к свойству (т.е. объявление его внутри определения свойства), чтобы полностью скрыть его и гарантировать, что доступ к нему можно получить только через свойство.
возможно, есть вариант использования с вложенными / наследуемыми классами или, возможно, когда get/set может содержать логику вместо того, чтобы просто возвращать значение свойства
Я лично использую это, даже когда мне не нужна логика в getter или setter свойства. Использование свойства, даже приватного, помогает защитить ваш код на будущее, чтобы вы могли добавить логику в getter позже, если потребуется.
Если я чувствую, что свойство может потребовать дополнительной логики, я иногда оборачиваю его в частное свойство вместо использования поля, просто чтобы не менять код позже.
В полусвязанном случае (хотя и отличном от вашего вопроса) я очень часто использую приватные сеттеры для публичных свойств:
public string Password
{
get;
private set;
}
Это дает вам публичный геттер, но сохраняет сеттер приватным.
Основное использование этого в моем коде - ленивая инициализация, как уже упоминалось другими.
Другая причина, по которой частные свойства преобладают над полями, заключается в том, что частные свойства намного проще отлаживать, чем частные поля. Я часто хочу знать такие вещи, как «это поле устанавливается неожиданно; кто первый вызывающий, который устанавливает это поле?» и это будет намного проще, если вы можете просто поставить точку останова на сеттер и нажать go. Вы можете поставить логин туда. Вы можете поместить туда показатели производительности. Вы можете ввести проверки согласованности, которые выполняются в отладочной сборке.
По сути, все сводится к следующему: код намного мощнее данных . Любая техника, позволяющая написать нужный мне код, хороша. Поля не позволяют писать в них код, в отличие от свойств.
Я использую их при сериализации, с помощью таких вещей, как DataContractSerializer
или protobuf-net, которые поддерживают это использование (XmlSerializer
не поддерживает). Это полезно, если вам нужно упростить объект как часть сериализации:
public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
get { return SomeProp.ToInt32(); }
set { SomeProp = SomeComplexType.FromInt32(value); }
}