应该将“行动”代表重构为新方法吗?

时间:2009-03-27 17:35:13

标签: .net generics refactoring

我有以下方法

    private void SetProcessDocumentStatus(string status)
    {
        var setStatusWith = new Action<string>(
            statusValue => processDocumentStatusLabel.Text = statusValue);
        if (processDocumentStatusLabel.InvokeRequired)
            processDocumentStatusLabel.Invoke(
                (MethodInvoker)(() => setStatusWith(status)));
        else
            setStatusWith(status);
    }

从上面的代码中,我将动作封装到setStatusWith中。 该行为是否应重构为另一种方法如下?

    private void SetProcessDocumentStatusWith(string status)
    {
        processDocumentStatusLabel.Text = status;
    }

    private void SetProcessDocumentStatus(string status)
    {
        if (processDocumentStatusLabel.InvokeRequired)
            processDocumentStatusLabel.Invoke(
                (MethodInvoker)(() => SetProcessDocumentStatusWith(status)));
        else
            SetProcessDocumentStatusWith(status);
    }

我想知道是否应该在代码中谨慎使用“Action”委托。

4 个答案:

答案 0 :(得分:5)

你所拥有的东西对我来说似乎非常清楚。将lambda移动到单独的函数会增加代码行但不清晰。

我可能会把第一行写成:

  Action<string> setStatusWith = 
    statusValue => processDocumentStatusLabel.Text = statusValue;

但我不知道哪种方式通常是首选。

答案 1 :(得分:2)

在示例中,您使操作接受参数:Action<string>,但之后您只传递相同的参数status。所以它不需要接受参数 - 也许你不知道lambda捕获变量的能力?

private void SetProcessDocumentStatus(string status)
{
    Action setStatusWith = () => processDocumentStatusLabel.Text = status;

    if (processDocumentStatusLabel.InvokeRequired)
        processDocumentStatusLabel.Invoke(() => setStatusWith());
    else
        setStatusWith();
}

或者调整Alan Jackson的优秀答案:

private void SetProcessDocumentStatus(string status)
{
    processDocumentStatusLabel.Run(ctrl => ctrl.Text = status);
}

public static class ControlExtensions
{
    public static void Run<T>(this TControl control, Action<TControl> action)
        where TControl : Control
    {
        if (control.InvokeRequired)
            control.Invoke(() => action(control));
        else
            action(control);
    }
}

这里我已经将Action作为参数取而代之。此外,我已将辅助方法变为扩展,这似乎是合理的。

答案 2 :(得分:1)

使用Action委托没有任何内在错误。我之所以说你应该有两个单独的方法的唯一原因是,如果你觉得你需要绕过检查以查看InvokeRequired属性是否为true并且调用必须被编组。但是,我认为没有明确的理由这样做。

就个人而言,我认为检查InvokeRequired然后编组调用自己的代码是个坏主意。我更喜欢调用者不得不意识到他们所处的环境(是UI线程还是没有),然后决定是否编组调用。

答案 3 :(得分:1)

如果有的话,我会包装逻辑来执行函数中的调用,因为这是将要多次使用的逻辑(基本上所有可以设置为异步的函数)。

    private void SetProcessDocumentStatus(string status)
    {
        RunOnControl<string>(
            processDocumentStatusLabel, 
            statusValue => processDocumentStatusLabel.Text = statusValue,
            status);
    }

    private void RunOnControl<T>(Control control, Action<T> action, T param)
    {
        if (control.InvokeRequired)
            control.Invoke(action, param);
        else
            action(param);
    }