Artium
Artium

Reputation: 5329

Caching Intensive Calculation in Property Getter

In the following code:

public class SomeClass
{
    // ... constructor and other stuff

    public in SomeProperty
    {
        get
        {
            return SomeHeavyCalculation();
        }
    } 
}

I consider the class to be immutable, so every time SomeProperty is accessed, same value should be returned. My question is whether it is possible to avoid calculating the value each time. Is there some built in mechanism for caching such stuff?

Upvotes: 12

Views: 4037

Answers (4)

Johnny5
Johnny5

Reputation: 6882

Just keep a flag to remember if the calculation have been done.

public class SomeClass
{
    // ... constructor and other stuff

   private bool _propertyCalculated;
   private int _someProperty;

    public int SomeProperty
    {
        get
        {
            if (!_propertyCaculated)
            {
                _someProperty = SomeHeayCalculation();
                _propertyCaculated = true;
            }
            return _someProperty;
        }
    } 
}

Upvotes: 2

Chris Snowden
Chris Snowden

Reputation: 5002

Just cache the calculation in a private variable like so:

public class SomeClass
{        
    // ... constructor and other stuff

    private int? calculation = null;

    public int SomeProperty
    {
        get
        {
            if (!calculation.HasValue)
                calculation = SomeHeayCalculation();

            return calculation.Value;
        }
    } 
}

Upvotes: 5

Marc
Marc

Reputation: 9354

Other than what Jon suggested, you could use this pattern:

public class SomeClass
{
    // ... constructor and other stuff
    private Foo _foo;

    public Foo SomeProperty
    {
        get
        {
            return _foo ?? (_foo = SomeHeayCalculation());
        }
    } 
}

It's worth noting that this really breaks down (read: becomes less readable) for value types, unless you want to wrap them in Nullable<T>. In that's your case, you may want to stick with Lazy<T> if available.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1503290

Yup - Lazy<T>, assuming you're using .NET 4:

public class SomeClass
{
    private readonly Lazy<Foo> foo = new Lazy<Foo>(SomeHeayCalculation);
    // ... constructor and other stuff

    public Foo SomeProperty
    {
        get
        {
            return foo.Value;
        }
    } 
}

I assume you're trying to avoid performing the calculation if the property is never accessed. Otherwise, just perform it upfront on construction.

Note that properties are often understood to be "cheap" to evaluate - and while you're making this lazy so that later accesses are cheap, this is still potentially going to be "heavy" enough on the first access to make a property inappropriate. Consider a ComputeXyz method instead.

Upvotes: 22

Related Questions