c# - 在这种情况下有没有比 GOTO 更好的方法?

标签 c#

让我们以一点诚实开始。我不喜欢 goto,但我也不喜欢一遍又一遍地重复我的代码。无论如何,我遇到了这种情况。这很不寻常,但并非超出这个世界。我不禁想知道这是否适合 goto。有没有更好的办法?

public Task Process(CancellationTokenSource token)
{
    await SpinUpServiceAsync();
    foreach (var item in LongList())
    {
        if (token.IsCancellationRequested) goto cancel;
        await LongTask1(item);

        if (token.IsCancellationRequested) goto cancel;
        await LongTask2(item);

        if (token.IsCancellationRequested) goto cancel;
        await LongTask3(item);

        if (token.IsCancellationRequested) goto cancel;
        await LongTask4(item);

        if (token.IsCancellationRequested) goto cancel;
        await LongTask5(item);

        continue;
        cancel:
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
    }
}

这是我看到的下一个最佳选择:

public Task Process(CancellationTokenSource token)
{
    await SpinUpServiceAsync();
    foreach (var item in LongList())
    {
        if (token.IsCancellationRequested)
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
        await LongTask1(item);

        if (token.IsCancellationRequested)
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
        await LongTask2(item);

        if (token.IsCancellationRequested)
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
        await LongTask3(item);

        if (token.IsCancellationRequested)
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
        await LongTask4(item);

        if (token.IsCancellationRequested)
        {
            Log($"Cancelled during {item}");
            await SpinDownServiceAsync();
            return;
        }
        await LongTask5(item);
    }
}

但是看看那些不必要的重复。

感谢您的考虑。

最佳答案

我没有 LongTask1-5 的确切类型,但我会这样做。

public Task Process(CancellationTokenSource token)
{
    SOMETYPE[] tasks = new SOMETYPE[] {LongTask1, LongTask2, LongTask3, LongTask4, LongTask5};
    await SpinUpServiceAsync();
    foreach (var item in LongList())
    {

        foreach(var task in tasks){
            if (token.IsCancellationRequested) {
                Log($"Cancelled during {item}");
                await SpinDownServiceAsync();

                return;
            }
            await task(item);
        }



    }
} 

这种方法将任务放在一个数组中。如果需求发生变化,需要执行更多任务,则数组定义会变长,但其余代码保持不变。好的代码使用循环来完成重复性任务,而不是像原始帖子中那样进行大量复制和粘贴。

关于c# - 在这种情况下有没有比 GOTO 更好的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39047926/

相关文章:

c# - 本地化日期范围

c# - 使用 Simple Injector 注册泛型类型的实例创建者

c# - 如何让 EventLog 将用户名记录到 Window 事件日志中?

c# - 创建具有名称的对象以注入(inject)单元测试

c# - DataGridView使用虚拟方式实时展示datatable

c# - 仍然可以改变物体的值(value)

c# - 加载 Matlab 程序集时流氓等待 40 秒......如何诊断原因?

c# - 如何在 C# 中制作一个公共(public)秒表

c# - 设计进程监视器 Windows 服务

c# - 发布到发送 NULL 值的 WCF 服务