函数式 C# - 使用或返回 Action

发布于 2024-09-29 22:11:02 字数 720 浏览 2 评论 0原文

为了更好地处理 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# 中开发高阶函数时的首选策略吗?

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

Browsing the net for better fault handling in C#, I've com across the following to implementation strategies. The first one is natural to me, while the other implementation I'm not certain what its advantages are?

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

Is 2) the preferred strategy when developing higher order functions in C#?

And, I am wondering, if one approach is more efficient than the other.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

明天过后 2024-10-06 22:11:02

第二种情况就像一个错误的动作工厂。在其中传递您想要执行的操作的委托 protectedBlock,以及发生 Exception 时执行操作的委托 faultHandler。这些操作将作为聚合 Action 包装在 try/catch 结构中返回。我对这两种方法的问题是实际上没有捕获Exception,因此谁要捕获你的抛出异常就没有信息来执行操作。

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

The second case is like a Faultable Action Factory. Where you pass in a delegate of what you want to do, protectedBlock, and a delegate of what to do when an Exception occurs, faultHandler. The actions are returned wrapped in a try/catch structure as an aggregate Action. My problem with both these methods is no Exception is actually being caught so who ever is going to catch your throw has no information on which to act.

The difference in execution between the 2 is when they actually execute. The 1st will be executed when it's called. The 2nd will execute whenever the returned Action is called. I don't think the efficiency difference would be significant.

瀞厅☆埖开 2024-10-06 22:11:02

(2)可以进一步组合,而(1)只是运行。但两者都不是完全“函数式”的,因为 Action 不是函数(与 Func 相比)。

因此,对于(2),你可以这样做:

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

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

(2) can be further composed, whilst (1) just runs. But neither are exactly "functional" as Action is not a function (compare with Func<A, R>).

So with (2) you could do:

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

...and get expected behavior. That doesn't work with (1)

难得心□动 2024-10-06 22:11:02

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

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

出于这些原因,我更喜欢方法 1。如果需要推迟执行,可以显式引入 lambda“() => Fault(a, b)”。

In C#, approach 2 can be confusing. A caller might use "Fault(a, b);" expecting a and possibly b to be called. Instead, a lambda is created, returned and discarded. In other words nothing is done.

Regarding efficiency, approach 2 is a bit wasteful if most of your calls are of the form "Fault(a,b)();", i.e. you invoke the lambda immediately. In this situation, you don't need a lambda.

For these reasons, I would prefer approach 1. If you need to defer execution, you can introduce a lambda explicitly "() => Fault(a, b)".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文