Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy property requiring "this"

Here is an example of a property I have, coded as simply as possible

private IEnumerable<int> _blocks;
private bool _blocksEvaluated;
public IEnumerable<int> Blocks
{
    get
    {
        if (!_blocksEvaluated)
        {
            _blocksEvaluated = true;
            _blocks = this.CalculateBlocks(0).FirstOrDefault();
        }
        return _blocks;
    }
}

This is verbose; I would like to make it more concise if possible. The following would be acceptable...

private Lazy<IEnumerable<int>> _blocks = 
    new Lazy<IEnumerable<int>>(() => this.CalculateBlocks(0).FirstOrDefault());

... but it doesn't compile.

Keyword 'this' is not valid in a static property, static method, or static field initializer

So I came up with the following

struct MyLazy<TResult>
{
    private bool evaluated;
    private TResult result;

    public TResult Evaluate(Func<TResult> func)
    {
        if (!evaluated)
        {
            evaluated = true;
            result = func();
        }
        return result;
    }
}

private MyLazy<IEnumerable<int>> _blocks;
public IEnumerable<int> Blocks
{
    get { return _blocks.Evaluate(() => this.CalculateBlocks(0).FirstOrDefault()); }
}

Which I like best, but is there a better way?

Note - I realize that mutable structs are usually evil, but they seem really useful for this one particular problem.

like image 746
default.kramer Avatar asked Aug 05 '13 16:08

default.kramer


People also ask

When did the lazy property initialize?

lazy initialisation is a delegation of object creation when the first time that object will be called. The reference will be created but the object will not be created. The object will only be created when the first time that object will be accessed and every next time the same reference will be used.

What are lazy properties in Kotlin?

Lazy propertieslazy() is a function that takes a lambda and returns an instance of Lazy<T> , which can serve as a delegate for implementing a lazy property. The first call to get() executes the lambda passed to lazy() and remembers the result. Subsequent calls to get() simply return the remembered result.

What is lazy instantiation in C#?

Lazy initialization of an object means that its creation is deferred until it is first used. (For this topic, the terms lazy initialization and lazy instantiation are synonymous.) Lazy initialization is primarily used to improve performance, avoid wasteful computation, and reduce program memory requirements.

Is Lazy thread safe?

Making the Lazy<T> object thread safe does not protect the lazily initialized object. If multiple threads can access the lazily initialized object, you must make its properties and methods safe for multithreaded access.


2 Answers

Just initialize your field in the constructor.

public class MyClass
{
    public MyClass()
    {
        _blocks = new Lazy<IEnumerable<int>>(() => this.CalculateBlocks(0).FirstOrDefault());
    }

    private readonly Lazy<IEnumerable<int>> _blocks;
}
like image 61
Michael Gunter Avatar answered Oct 19 '22 16:10

Michael Gunter


You can't use this when initializing an instance field, but you can simply initialize it in the constructor to address that.

private Lazy<IEnumerable<int>> _blocks;

public MyClass()
{
   _blocks = new Lazy<IEnumerable<int>>(
         () => this.CalculateBlocks(0).FirstOrDefault());
}

public IEnumerable<int> Blocks
{
    get
    {
        return _blocks.Value;
    }
}
like image 25
Servy Avatar answered Oct 19 '22 16:10

Servy