Pergunta

Navegando pela rede para obter um melhor manuseio de falhas em C#, eu tenho o seguinte as seguintes estratégias de implementação. O primeiro é natural para mim, enquanto a outra implementação não tenho certeza de quais são suas vantagens?

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) A estratégia preferida ao desenvolver funções de ordem superior em C#?

E, estou me perguntando, se uma abordagem é mais eficiente que a outra.

Foi útil?

Solução

O segundo caso é como uma fábrica de ação falha. Onde você passa um delegado do que você quer fazer, protectedBlock, e um delegado do que fazer quando um Exception ocorre faultHandler. As ações são devolvidas embrulhadas em uma estrutura de tentativa/captura como um agregado Action. Meu problema com esses dois métodos é não Exception está realmente sendo pego, então quem vai pegar seu arremesso não tem informações sobre as quais agir.

A diferença na execução entre os 2 é quando eles realmente executam. O primeiro será executado quando for chamado. O segundo será executado sempre que o retorno Action é chamado. Eu não acho que a diferença de eficiência seria significativa.

Outras dicas

(2) pode ser composto ainda mais, enquanto (1) apenas executa. Mas também não são exatamente "funcionais" como Action não é uma função (compare com Func<A, R>).

Então, com (2) você pode fazer:

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

... e obtenha comportamento esperado. Isso não funciona com (1)

Em C#, a abordagem 2 pode ser confusa. Um chamador pode usar "Falha (A, B);" Esperando que A e possivelmente B sejam chamados. Em vez disso, um lambda é criado, devolvido e descartado. Em outras palavras, nada é feito.

Em relação à eficiência, a abordagem 2 é um pouco desperdiçada se a maioria das suas chamadas for do formulário "Falha (a, b) ();", ou seja, você invoca o lambda imediatamente. Nesta situação, você não precisa de um lambda.

Por esses motivos, eu preferiria a abordagem 1. Se você precisar adiar a execução, poderá apresentar um lambda explicitamente "() => falha (a, b)".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top