Есть ли причины использовать частные объекты в С#?
Я только понял, что конструктор свойств С# также может использоваться с модификатором доступа 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 изменяет имена и, таким образом, разрушает сериализатор)