当我遇到类似问题时发现了这个问题,并想找到一个好的模式来使用。
其他答案中建议的“将初始化移动到构造函数”的问题是初始化函数的 lambda 现在出现在构造函数中(实际上,在以前不需要的类中现在需要显式构造函数)。
这个玩具示例很好,但是在一个具有许多属性的更复杂的类中,将与属性相关的所有逻辑放在一个地方很有用。
亚历克斯·西普曼的回答提出了一个很好的选择,但是托管该LazyValue<>
课程的第三方网站现在似乎是“服务不可用”,无论如何我都不是在寻找第三方解决方案,只是一种与正常情况一起使用的有效模式Lazy<>
班级。我还担心在某些用例中,每次访问属性时创建委托实例和关联的闭包可能并非易事。
由于其他答案中突出显示的问题,在构造函数中有一行似乎是不可避免的,但我似乎最好避免将属性逻辑放在构造函数本身中,因为它将与任何差异等中的属性分开。
以下两种模式似乎有效,但我不确定是否有更好的选择我错过了。
模式 1:不要费心使用 lambda - 在属性旁边声明一个真实函数,并将其包装在隐式委托中:
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; }
}
模式 2:声明一个属性 init 函数并从构造函数中调用它。
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)); }
}
看到两者并排,我想我更喜欢第二个,除了函数的名字看似笨拙。
[在我的实际实现中,我有一个类似于 的名称InitSum
,因此它是“惰性”属性的实现细节,原则上可以在惰性和非惰性实现之间进行更改,而无需更改构造函数代码]