3

浏览网络以在 C# 中更好地处理故障,我已经了解了以下实现策略。第一个对我来说很自然,而另一个实现我不确定它的优点是什么?

1)

static void Fault(Action protectedBlock, Action faultHandler)
{ 
    try
    {
        protectedBlock();
    }
    catch
    {
        faultHandler();
        throw;
    }
}

2)

static Action Fault(Action protectedBlock, Action faultHandler)
{
    return () =>
    {
        try
        {
            protectedBlock();
        }
        catch
        {
            faultHandler();
            throw;
        }
    };
}

2) 是在 C# 中开发高阶函数时的首选策略吗?

而且,我想知道,如果一种方法比另一种更有效。

4

3 回答 3

5

第二种情况就像一个故障动作工厂。你传入一个你想要做什么protectedBlock的代表,以及一个代表当一个Exception发生时要做什么的代表,faultHandler。动作被包装在一个 try/catch 结构中作为一个聚合返回Action。我对这两种方法的问题Exception是实际上没有被抓住,所以谁会抓住你的投掷没有关于采取行动的信息。

两者之间的执行差异在于它们实际执行的时间。第一个将在调用时执行。每当调用返回时,第二个将执行Action。我认为效率差异不会很大。

于 2010-10-27T13:47:04.723 回答
4

(2) 可以进一步组合,而 (1) 只是运行。但两者都不完全是“功能性的”,因为Action它不是功能(与 比较Func<A, R>)。

所以使用(2)你可以这样做:

Fault(someAction, Fault(firstTryFaultHandler, lastDitchFaultHandler))();

...并获得预期的行为。这不适用于(1)

于 2010-10-27T13:38:24.810 回答
1

在 C# 中,方法 2 可能会令人困惑。调用者可能会使用“Fault(a, b);” 期望调用 a 并且可能调用 b。相反,一个 lambda 被创建、返回和丢弃。换句话说,什么都不做。

关于效率,如果您的大多数调用都是“Fault(a,b)();”的形式,即您立即调用 lambda,则方法 2 有点浪费。在这种情况下,您不需要 lambda。

由于这些原因,我更喜欢方法 1。如果您需要延迟执行,您可以显式地引入一个 lambda "() => Fault(a, b)"。

于 2010-10-27T13:57:40.937 回答