在返回之前测试属性是否为空

时间:2010-03-25 14:31:07

标签: c#

我有以下属性

public MyType MyProperty {get;set;}

我想更改此属性,以便如果该值为null,它将首先填充该值,然后将其返回...但不使用使用私有成员变量。

例如,如果我这样做:

public MyType MyProperty 
{
    get
    {
        if (_myProperty != null)
            return _myProperty
        else
           _myProperty = XYZ;
            return _myProperty;
    }
    set
    {
        _myProperty = value;
    }
}
这可能吗?或者我是否需要成员变量来完成它?

13 个答案:

答案 0 :(得分:33)

您需要一个成员变量和一个完整的属性声明。自动实现的属性适用,如果它们是字段周围的琐碎包装器,不涉及逻辑。你可以稍微简化你的getter代码,顺便说一下:

get
{
    if (_myProperty == null)
    {
       _myProperty = XYZ;
    }
    return _myProperty;
}

(请注意,如果没有额外的锁定,这些都不是线程安全的,但我认为没关系。)

顺便说一句,如果您使用自动实现的属性,那么您已经拥有私有成员变量 - 这只是编译器为您生成它。

答案 1 :(得分:12)

return _myProperty?? (_myProperty = XYZ);

答案 2 :(得分:10)

你能做的最好的事情就是在构造函数中给它一个值。我知道这样你就失去了“延迟加载”,但你不能同时拥有自动属性和延迟加载。

答案 3 :(得分:4)

您的代码:

public MyType MyProperty {get;set;}

请参阅“Automatic Properties”,这只是“语法糖”,因为您可以查看here

  

编译器为其生成字段   该属性,也生成了   get set中的代码指向   字段。

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;
        }
    }
}

因此,您的代码将始终由编译器生成的字段支持。

答案 4 :(得分:2)

您需要使用成员变量来完成它:

public class MyClass
{
    MyType _myProperty = null;

    public MyType MyProperty
    {    
        get
        {
            if(_myProperty == null)
                _myProperty = XYZ;

            return _myProperty;
        }
    }
}

答案 5 :(得分:1)

你需要一个私有变量来实现它,因为你的getter / setter中有逻辑。

答案 6 :(得分:1)

如果您希望对获取或设置属性的行为进行任何修饰,那么您将丢失编译器生成的存储位​​置,因此您必须自己将值存储在某处。在大多数情况下,私有成员变量最有意义。

答案 7 :(得分:1)

我建议考虑使用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 :(得分:0)

是的,这是可能的。但是你必须自己实现它,而不是自动属性。您的属性不一定只需要使用成员变量,尽管这是默认值。

请记住,属性实际上已转换为Getter和Setter方法,您可以在其范围内完成大量工作。虽然这种做法通常是气馁的。良好实践表明,属性访问应该是快速的,并且不会长时间阻止客户端代码。

你可以这样做:

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

答案 9 :(得分:0)

仅当您使用成员变量时。

通常,我将延迟加载与implementation of IDisposable结合使用,以便可以在Dispose方法中处理任何需要清理的变量。

答案 10 :(得分:0)

通过“成员变量”我假设你的意思是在属性get中定义的变量。是的,您当然不需要本地定义的变量。保存代码行代码的更常见模式是:

    if (_myProperty == null)
        _myProperty = XYZ;

    return _myProperty;

如果通过“成员变量”表示支持字段,那么是的,您确实需要一个。只有完全简单的“传递”字段/属性关系才能实现,而无需显式创建支持字段。 (即便如此,它也是由编译器创建的。)要实例化-if-null,您需要明确定义它。

答案 11 :(得分:0)

如果该属性是必需的,那么一些检查可以使其成为防弹。我倾向于使用类似的东西:

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

使TDD更简单。

答案 12 :(得分:0)

试试这个

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
    }    
}