Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you locally encapsulate a field value for the purpose of lazy access?

The following snippets demonstrate a question that I have been encountering alot lately.

Basically I want to know if there is a better solution to hiding the backing value of a property than the use of inheritance as shown.

As a side question, is the feature implied by my non-compiling solution something that might be good for a future version of C#?

// This is a service that supplies a value but doesn't want to be called 
// until needed.
static class Service
{
    public static int GetP()
    {
        Console.WriteLine ("doing work...");
        return 1;
    }
}

// This is a class that implements a property which calls the service
// the first time that property is accessed but nothing stops the
// same code from accidentally referencing the uninitialized backing value.
class C
{
    void F()
    {
        // Easy to accidentally reference backing value of property
        Console.WriteLine (this.p);
    }

    int p = 0;
    int P
    {
        get
        {
            if(p == 0)
                p = Service.GetP();
            return p;
        }
    }
}

Solution using inheritance and protected property with private backing value.

// This class hides the backing value and exposed the property the derived class.
class CBase
{
    int p = 0;
    protected int P
    {
        get
        {
            if(p == 0)
                p = Service.GetP();
            return p;
        }
    }
}

class C1 : CBase
{
    void F()
    {
        // Now I can't see the backing value but I've used inheritance for the sole purpose of hiding it
        Console.WriteLine (this.P);
    }
}

What about if a const could be in the body of an instance level method/property that delayed setting until first runtime usage?

class D
{
    int P
    {
        get
        {
            const int a = Service.GetP(); // Doesn't compile
            return a;
        }
    }
}
like image 868
Aaron Anodide Avatar asked Dec 22 '25 00:12

Aaron Anodide


1 Answers

If you're using .net 4, just use the Lazy class

class C
{
    private Lazy<int> p = new Lazy<int>(() => Service.GetP());

    private int P
    {
        get
        {
            return p.Value;
        }
    }
}

The first time you access Lazy.Value, the function supplied to the constructor will be called to initialize the value.

like image 86
Trevor Pilley Avatar answered Dec 23 '25 15:12

Trevor Pilley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!