5

我有很多代码必须在初始化期间运行一次。

我必须以这种方式使用布尔标志,因为它在一个事件中

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;
}

当然,它有效,但我只是适度满意,我相信还有更优雅的解决方案。什么是你的?

4

3 回答 3

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;
  // ...
}
于 2012-03-28T09:36:23.927 回答
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 
    }
} 
于 2012-03-28T09:37:30.060 回答
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;

    // ...
}

但是如果你发现自己经常使用这种模式,这可能表明重构是有序的。也许只是为某些变量分配默认值?无论如何,他们为什么不初始化?

于 2012-03-28T09:56:07.053 回答