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.
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.
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.
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.
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.
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;
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With