Found this question when I had a similar issue, and wanted to find a good pattern to use.
The issue with "move the initialisation to the constructor" suggested in other answers is that the lambda for the initialization function now appears in the constructor (and indeed an explicit constructor is now required in a class which didn't previously need one).
Fine for this toy example, but in a more complicated class with many properties, it is useful to have all the logic relating to the property in one place.
Alex Siepman's answer suggests a neat alternative, but the third party site hosting the LazyValue<>
class seems to be "Service unavailable" right now, and in any case I wasn't looking for a third party solution, merely an efficient pattern to use with the normal Lazy<>
class. I'm also concerned that in some use cases, creating the delegate instance and associated closure each time the property is accessed may be non-trivial.
Having a line in the constructor seems unavoidable, due to the issues highlighted in other answers, but it seems preferable to me to avoid putting the property logic in the constructor itself, as it will be so far separated from the property in any diffs etc.
The following 2 patterns seem to work, but I'm not sure whether there's an even better alternative I missed.
Pattern 1: don't bother using a lambda - declare an real function next to the property, and wrap it in an implicit delegate:
public class MyClass
{
public MyClass()
{
lazyGetSum = new Lazy<int>(GetSum);
}
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum;
public int Sum { get { return lazyGetSum.Value; } }
private int GetSum() { return X + Y; }
}
Pattern 2: Declare a property init function and call that from the constructor.
public class MyClass
{
public MyClass()
{
LazyGetSumInit();
}
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum;
public int Sum { get { return lazyGetSum.Value; } }
private void LazyGetSumInit() { lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y)); }
}
Seeing the two side by side, I think I prefer the second, except for the seemingly clumsy name for the function.
[In my real implementation, I had a name similar to InitSum
, so that it's an implementation detail of the property that it's "lazy", and it can in principle be changed between a lazy and non-lazy implementation without changing the constructor code]