Проверьте, не является ли свойство не нулем перед возвратом
У меня есть следующее свойство
public MyType MyProperty {get;set;}
Я хочу изменить это свойство, чтобы, если значение равно null, оно сначала заполнит значение, а затем вернет его... но без использования частной переменной-члена.
Например, если бы я делал это:
public MyType MyProperty
{
get
{
if (_myProperty != null)
return _myProperty
else
_myProperty = XYZ;
return _myProperty;
}
set
{
_myProperty = value;
}
}
Это возможно? Или мне нужна переменная-член, чтобы сделать это?
Ответы
Ответ 1
Вам нужна переменная-член и объявление полной собственности. Автоматически реализованные свойства применимы только в том случае, если они представляют собой тривиальные обертки вокруг поля, без какой-либо логики. Вы можете немного упростить свой код геттера, btw:
get
{
if (_myProperty == null)
{
_myProperty = XYZ;
}
return _myProperty;
}
(Обратите внимание: ничто из этого не является потокобезопасным без дополнительной блокировки, но я предполагаю, что все в порядке.)
Кстати, у вас уже есть переменная private member, если вы используете автоматически реализованные свойства - это просто то, что компилятор генерирует ее для вас.
Ответ 2
Лучшее, что вы можете сделать, это присвоить ему значение в конструкторе. Я знаю, что таким образом вы теряете "ленивую загрузку", но вы не можете иметь автоматические свойства и ленивую загрузку в одно и то же время.
Ответ 3
return _myProperty?? (_myProperty = XYZ);
Ответ 4
Ваш код:
public MyType MyProperty {get;set;}
см. "" Автоматические свойства ", которые являются просто" синтаксическим сахаром ", так как вы можете проверить здесь.
Компилятор генерирует поле для собственности, а также генерирует кода в наборе get, чтобы указать на поле.
internal class ClassName
{
// Fields
[CompilerGenerated]
private MyType <Property>k__BackingField;
// Properties
public MyType MyProperty
{
[CompilerGenerated]
get
{
return this.<Property>k__BackingField;
}
[CompilerGenerated]
set
{
this.<Property>k__BackingField = value;
}
}
}
Таким образом, ваш код будет всегда подкрепляться генерируемым компилятором полем.
Ответ 5
Вам понадобится приватная переменная, чтобы реализовать это, потому что у вас есть логика в ваших getter/seters.
Ответ 6
Если вы хотите сделать какое-либо приукрашивание при получении или настройке поведения свойства, тогда вы потеряете место хранения сгенерированного компилятором, поэтому вам нужно будет сохранить значение где-то самостоятельно. Частная переменная-член имеет наибольший смысл, большую часть времени.
Ответ 7
Я предлагаю использовать Lazy initialization.
Это не поможет вам избежать переменной-члена, поэтому сожалею об этом, но этот код поможет вам избежать резервирования памяти для переменной-члена, пока ваш класс не понадобится этой переменной:
public class MyType
{
public MyType()
{
XYZ();
}
public void XYZ()
{
//some kind of initialization
}
}
public class TestType
{
private Lazy<MyType> _myProperty;
public MyType MyProperty
{
get { return _myProperty.Value; }//_myProperty will be null until some code will try to read it
}
}
Еще одна вещь, чтобы указать или на самом деле напомнить, вы не сможете быть абсолютно без переменной-члена. Потому что за занавесками компилятор .Net будет создавать эту переменную-член вместо вас. Он просто не уведомит вас об этом шаге. Но, как было упомянуто другими, если вы посмотрите в сгенерированном MSIL, вы увидите, что переменная-член создана для вас.
Ответ 8
Вам нужна переменная-член, чтобы сделать это:
public class MyClass
{
MyType _myProperty = null;
public MyType MyProperty
{
get
{
if(_myProperty == null)
_myProperty = XYZ;
return _myProperty;
}
}
}
Ответ 9
Да, это возможно. Но вы должны реализовать его самостоятельно, а не с авто свойствами. Ваши свойства необязательно должны работать только с переменными-членами, хотя это значение по умолчанию.
Помните, что свойства фактически превращаются в методы Getter и Setter, и вы можете выполнять большую работу в рамках своей области. Хотя эта практика обычно обескуражена. Хорошая практика утверждает, что доступ к ресурсу должен быть быстрым, а не блокировать код клиента для длительных периодов времени.
Вы могли бы просто сделать это:
public MyType MyProperty
{
get
{
if (_myProperty != null)
return _myProperty
else
return XYZ;
}
set
{
_myProperty = value;
}
}
Ответ 10
Только при использовании переменной-члена.
Обычно я совмещаю ленивую загрузку с реализацией IDisposable, так что любые переменные, которые необходимо очистить, можно обрабатывать в Утилизировать метод.
Ответ 11
Под "переменной-членом" я предполагаю, что вы имеете в виду переменную, определенную внутри свойства get. Да, конечно, вам не нужна локально определенная переменная. Более распространенный шаблон, который сохраняет строки кода связи, равен:
if (_myProperty == null)
_myProperty = XYZ;
return _myProperty;
Если по переменной-члену вы имеете в виду поле поддержки, то да, вам это нужно. Могут быть реализованы только простейшие "сквозные" отношения между полями и свойствами без явного создания поля поддержки. (И даже тогда он создается компилятором.) Чтобы создать экземпляр-if-null, вам нужно явно определить его.
Ответ 12
Если требуется свойство, то некоторые проверки могут сделать его пуленепробиваемым. Я обычно использую что-то вроде:
public MyType MyProperty
{
get
{
if (_myProperty == null)
_myProperty == XYZ;
return _myProperty;
}
set
{
if(value == null)
throw InvalidArgumentException();
_myProperty = value;
}
}
Делает TDD более простым.
Ответ 13
Попробуйте это
Public Class MyClass
{
Public MyType Alfa
{
If(this._Alfa == null) this.SetAlfa();
return _Alfa;
}
private MyType _Alfa {get;set;}
private void SetAlfa()
{
//Somenthing to valorize _Alfa
}
}