Saw*_*wan 47 .net c# .net-4.0 lazy-evaluation
我有这个代码:
public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
public int Sum{ get { return lazyGetSum.Value; } }
}
Run Code Online (Sandbox Code Playgroud)
给我这个错误:
字段初始值设定项不能引用非静态字段,方法或属性.
我认为通过懒惰访问非静态成员是非常合理的,怎么做?
*编辑*
接受的答案完美地解决了这个问题,但是要看到问题的详细和深入 - 总是原因,你可以阅读Joh Skeet的答案.
Jle*_*HeP 77
您可以将其移动到构造函数中:
private Lazy<int> lazyGetSum;
public MyClass()
{
lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
}
Run Code Online (Sandbox Code Playgroud)
有关问题原因的详细信息,请参阅下面的@JohnSkeet答案. 通过Lazy <T>或任何lambda表达式访问非静态成员
Jon*_*eet 58
这是您问题的简化版本:
class Foo
{
int x = 10;
int y = this.x;
}
Run Code Online (Sandbox Code Playgroud)
一个稍微简化的一个:
class Foo
{
int x = 10;
Func<int> y = () => this.x;
}
Run Code Online (Sandbox Code Playgroud)
(这this通常是含蓄的,但为了清楚起见,我在这里明确了这一点.)
在第一种情况下,使用this非常明显.
在第二种情况下,它稍微不那么明显,因为它由于lambda表达式而延迟.它仍然不被允许...因为编译器会尝试构建一个用作this目标的委托,如下所示:
class Foo
{
int x = 10;
Func<int> y = this.GeneratedMethod;
private int GeneratedMethod()
{
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
这是C#5规范第10.5.5.2节所禁止的:
实例字段的变量初始值设定项无法引用正在创建的实例.
最简单的解决方法是只把初始化在构造函数体,你在哪里都能够引用this.所以在你的代码中:
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; } }
}
Run Code Online (Sandbox Code Playgroud)
请注意,我也简化了lambda表达式 - 它很少值得使用new Func<int>(...).