Подтвердить что ты не робот

Проверьте, не является ли свойство не нулем перед возвратом

У меня есть следующее свойство

public MyType MyProperty {get;set;}

Я хочу изменить это свойство, чтобы, если значение равно null, оно сначала заполнит значение, а затем вернет его... но без использования частной переменной-члена.

Например, если бы я делал это:

public MyType MyProperty 
{
    get
    {
        if (_myProperty != null)
            return _myProperty
        else
           _myProperty = XYZ;
            return _myProperty;
    }
    set
    {
        _myProperty = value;
    }
}

Это возможно? Или мне нужна переменная-член, чтобы сделать это?

4b9b3361

Ответ 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
    }    
}