Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load property lazy loading

I have a property which getter should load its value only the first time. The second time it returns the loaded value without loading it again:

private Object _MemberValue;

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

        return _MemberValue;
    }
}

In VB.NET there is the Static keyword. With it you don't have to declare a class wide member.

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

In C# there isn't such a keyword.

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

like image 439
user11909 Avatar asked Dec 11 '22 12:12

user11909


2 Answers

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

Probably not. You can use Lazy<T> as an replacement if you like, but basically it is the same as your first example. Using Static in VB.NET has some serious drawbacks, so I wouldn't use it either way.

If you prefer Lazy<T>, this is what I would use:

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

public object MemberValue
{
    get
    {
        return _MemberLazy.Value;
    }
}
like image 81
Patrick Hofman Avatar answered Dec 26 '22 22:12

Patrick Hofman


Your initial approach seems appropriate, I have never had reason to do something different. That said if your goal here is to avoid a class level field that could potentially be written to outside the getter, perhaps something like this would work. There are a number of other ReadOnly, WriteOnce, SetOnce implementations that would also work similarly.

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

It's not perfect. Unlike your VB.Net example; code outside of the getter could write to the field first, but at least you're protected from it being overwritten after Freeze is called.

like image 25
Derrick Moeller Avatar answered Dec 26 '22 22:12

Derrick Moeller