Question

Surfer sur le net pour une meilleure gestion des erreurs en C #, j'ai com à travers les éléments suivants aux stratégies de mise en œuvre. Le premier est naturel pour moi, alors que l'autre application je ne suis pas certain que ses avantages sont?

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

Est 2) la stratégie préférée lors de l'élaboration des fonctions d'ordre supérieur en C #?

Et, je me demande, si l'on approche est plus efficace que l'autre.

Était-ce utile?

La solution

Le second cas est comme une usine d'action Faultable. Où vous passez un délégué de ce que vous voulez faire, protectedBlock, et un délégué de ce qu'il faut faire lorsqu'un Exception se produit, faultHandler. Les actions sont retournées enveloppé dans une structure try / catch comme un Action global. Mon problème avec ces deux méthodes est pas Exception est en fait d'être pris alors qui va jamais attraper votre jet n'a pas d'informations sur lequel agir.

La différence d'exécution entre le 2 est quand ils procèdent à des exécutions. Le 1er sera exécuté quand elle est appelée. Le 2e exécutera chaque fois que le retour Action est appelé. Je ne pense pas que la différence d'efficacité serait importante.

Autres conseils

(2) peut encore être composé, tandis que (1) seulement fonctionne. Mais ne sont exactement « fonctionnelle » comme Action est pas une fonction (à comparer avec Func<A, R>).

Donc, avec (2), vous pouvez faire:

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

... et obtenir le comportement attendu. Cela ne fonctionne pas avec (1)

En C #, approche 2 peut être source de confusion. Un appelant peut utiliser "Fault (a, b);" attendant un et peut-être b à appeler. Au lieu de cela, un lambda est créé, retourné et mis au rebut. En d'autres mots rien est fait.

En ce qui concerne l'efficacité, l'approche 2 est un gaspillage de bits si la plupart de vos appels sont de la forme « défaut (a, b) (); », à savoir que vous invoquez le lambda immédiatement. Dans cette situation, vous n'avez pas besoin d'un lambda.

Pour ces raisons, je préfère l'approche 1. Si vous devez exécution defer, vous pouvez introduire un lambda explicitement "() => Défaut (a, b)".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top