why is Lazy<T> constrained to static contexts?
Asked Answered
V

3

32

I'd like to use Lazy T to implement memoization but the initialization function appears to require a static context.

For example, the following code refuses to compile, warning that non-static members a and b are inaccessible. It's not clear to me why this is so as the Lazy object is an instance member itself and has no visibility in a static context.

public class SomeExpensiveCalculation
{
    private int a;
    private int b;
    public Lazy<int> Result = new Lazy<int>(() => a + b); //nope!
}
Vennieveno answered 14/7, 2011 at 7:30 Comment(1)
The error here is not in Lazy but in the lambda expression. In the context of the lambda 'a' and 'b' do not exist yet.Santiagosantillan
U
35

Object initializers outside a constructor (or method) has to refer to static members only. This is because the instance hasn't been constructed until the constructor is run, hence the fields are not "ready yet" and therefor cannot be referenced. Static fields work because they are initialized before fields.

Note that the error isn't caused by Lazy<T>, it is caused by the lambda expression. The workaround (and proper way of doing this) is to initialize Result in a constructor.

Utilize answered 14/7, 2011 at 7:44 Comment(1)
For ChessHound: This is the WHY the code doesn't work. It has nothing to do with the Lazy type.Mammon
S
13

I don´t know why your code does not work, but this should work:

    public class SomeExpensiveCalculation
    {
        private int a;
        private int b;
        public Lazy<int> Result;
        public SomeExpensiveCalculation()
        {
             Result = new Lazy<int>(() => a + b);
        }
    }
Spooner answered 14/7, 2011 at 7:38 Comment(0)
I
1

Just to expand on @Ondra's answer, this can be used with an injected factory as well. One caveat - be wary of the relative lifespans of the lazy and the factory:

public class SomeClass
{
  private readonly Lazy<ISomeDependency> _lazyField;

  // Ctor
  public SomeClass(ISomeFactory factory)
  {
     _lazyField = new Lazy<ISomeDependency>(() => factory.Create());
  }
}
Irrawaddy answered 16/10, 2013 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.