Accessing a non-static member via Lazy<T> or any lambda expression
Solution 1:
You can move it into constructor:
private Lazy<int> lazyGetSum;
public MyClass()
{
lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
}
See @JohnSkeet answer below for more details about the reason of the problem. Accessing a non-static member via Lazy<T> or any lambda expression
Solution 2:
Here's a simplified version of your problem:
class Foo
{
int x = 10;
int y = this.x;
}
And a slightly less simplified one:
class Foo
{
int x = 10;
Func<int> y = () => this.x;
}
(The this
is usually implicit, but I've made it explicit here for the sake of clarity.)
In the first case, the use of this
is very obvious.
In the second case, it's slightly less obvious, because it's deferred due to the lambda expression. It's still not allowed though... because the compiler would try to build a delegate which used this
as the target, like this:
class Foo
{
int x = 10;
Func<int> y = this.GeneratedMethod;
private int GeneratedMethod()
{
return x;
}
}
This is prohibited by section 10.5.5.2 of the C# 5 spec:
A variable initializer for an instance field cannot reference the instance being created.
The simplest fix is just to put the initialization in the constructor body, where you are able to refer to this
. So in your code:
public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum;
public MyClass()
{
lazyGetSum = new Lazy<int>(() => X + Y);
}
public int Sum{ get { return lazyGetSum.Value; } }
}
Note that I've simplified the lambda expression as well - it's very rarely worth using new Func<int>(...)
.
Solution 3:
The error is telling you exactly what is wrong. You can't access a property in a Field Initializer.
Suppose your class is like:
public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => 2 + 3));
public int Sum { get { return lazyGetSum.Value; } }
}
Then it would compile without any problem. Since in your code you are accessing property X and Y in field initialization. You are getting the error.
You can also initialize them in constructor if you want:
public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum;
public int Sum { get { return lazyGetSum.Value; } }
public MyClass()
{
lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
}
}