加载 属性 延迟加载

Load property lazy loading

我有一个 属性,getter 应该只在第一次加载它的值。第二次它 returns 加载值而不再次加载它:

private Object _MemberValue;

public Object MemberValue
{
    get
    {
        if(_MemberValue == null)
        {
            _MemberValue = LoadMember();
        }

        return _MemberValue;
    }
}

在 VB.NET 中有 Static 关键字。有了它,您不必声明 class 宽成员。

Public Property MemberValue as Object
    Get
        Static value as Object = Nothing

        If (value is Nothing) Then
            value = LoadMember()
        End If

        Return value
    End Get
End Property

在 C# 中没有这样的关键字。

这个问题或其他模式是否有更好的 C# 实现?

你最初的做法似乎很合适,我从来没有理由做不同的事情。也就是说,如果您的目标是避免可能写入 getter 之外的 class 级别字段,那么 this 之类的内容可能会起作用。还有许多其他 ReadOnly、WriteOnce、SetOnce 实现也可以类似地工作。

ReadOnlyField.cs

public class ReadOnlyField<T>
{
    private bool _frozen;
    private T _value;

    public T Value
    {
        get { return _value; }
        set
        { 
            if (_frozen)
                throw new InvalidOperationException();

            _value = value;
        }
    }

    public void Freeze()
    {
        _frozen = true;
    }
}

YourObject.cs

public class YourObject
{
    private readonly ReadOnlyField<object> _someMember;

    public object MemberValue
    {
        get
        {
            if(_someMember.Value == null)
            {
                _someMember.Value = LoadMember();
                _someMember.Freeze();
            }

            return _someMember.Value;
        }
    }

    public YourObject()
    {
        _someMember = new ReadOnlyField<object>();
    }
}

它并不完美。与您的 VB.Net 示例不同; getter 之外的代码可以先写入该字段,但至少在调用 Freeze 后您不会被覆盖。

Are there better C# implementations of this problem or other patterns?

可能不会。如果愿意,您可以使用 Lazy<T> 作为替代,但基本上它与您的第一个示例相同。在 VB.NET has some serious drawbacks 中使用 Static,所以我不会以任何方式使用它。

如果您更喜欢Lazy<T>,这就是我要使用的:

private Lazy<object> _MemberLazy = new Lazy<object>(LoadMember);

public object MemberValue
{
    get
    {
        return _MemberLazy.Value;
    }
}