我有很多代码必须在初始化期间一次运行。
我必须以这种方式使用布尔标志,因为它处于事件
中bool _fuse;
void PerformLayout()
{
Size size;
if (!_fuse)
{
size = _InitialContainerSize;
_fuse = true;
}
else
size = parent.Size;
// ...
}
因为它经常发生,我做了一些事情来使这个布尔变量看起来像保险丝:
所以我这样做了:
bool _fuse;
void PerformLayout()
{
Size size;
if (!Burnt(ref _fuse))
size = _InitialContainerSize;
else
size = parent.Size;
// ...
}
如果它初始化为false,则查询结果返回false一次,将切换为true,连续调用返回true。
public static bool Burnt(ref bool value)
{
if (!value)
{
value = true;
return false;
}
else
return true;
}
当然,它有效,但我只是中度满意,我相信有更优雅的解决方案。你的是什么?
答案 0 :(得分:1)
您可以使用可空类型和空合并运算符来声明Size
属性:
Size? _containerSize;
Size ContainerSize {
get {
return (_containerSize ?? (_containerSize = _InitialContainerSize)).Value;
}
}
然后您可以像这样使用它:
void PerformLayout() {
var size = ContainerSize;
// ...
}
如果要延迟初始化的类型是引用类型,它会变得更简单。
另一种选择是使用Lazy<T>
类型。这可用于上述代码可能破坏的多线程场景:
Lazy<Size> _containerSize = new Lazy<Size>(() => _InitialContainerSize);
void PerformLayout() {
var size = _containerSize.Value;
// ...
}
答案 1 :(得分:1)
实现这一目标的方法有很多种。您可以创建一个复杂的状态机来执行您的逻辑(最快),但在许多情况下,这将是过度的。或者,您可以像现在一样跟踪保存实例状态的布尔值。您还可以决定将两种解决方案组合到一个简单的状态机中,使用类似(快速模式)的方法:
public class TestClass
{
private Action performLayoutAction;
public TestClass()
{
// initial state
performLayoutAction = InitializePeformLayout;
}
public void PerformLayout()
{
performLayoutAction();
}
private void InitializePeformLayout()
{
// whatever
performLayoutAction = ContiniousPerformLayout;
}
private void ContiniousPerformLayout()
{
// whatever
}
}
答案 2 :(得分:1)
我认为避免重复的一般主旨是正确的(即使重复很小......但仍然如此)。只需将其封装并正确命名即可:
struct InitializerGuard {
private bool hasRun;
public bool HasRun() {
if (hasRun)
return true;
hasRun = true;
return false;
}
}
用法:
InitializerGuard sizeInitializer;
void PerformLayout()
{
Size size;
if (!sizeInitializer.HasRun())
size = _InitialContainerSize;
else
size = parent.Size;
// ...
}
但是如果你发现自己经常使用这种模式,这可能表明重构是有序的。也许只是为某些变量分配默认值?无论如何,他们为什么不初始化?