2009-11-13 11 views
0

J'ai une classe qui implémente IDisposableComment la classe jetable peut-elle détecter s'il existe une exception en cours?

public class Foo: IDisposable { 
    public void Dispose() { 
     // do the disposing 
    } 
} 

Puis-je avoir une méthode qui utilise la classe de la manière suivante:

void Bar() { 
    using (var f = new Foo()) { 
     // do whatever 
    } 
} 

Lorsque le code quitte la limite en utilisant {...}, la méthode Dispose sur la classe Foo est appelée. Comment puis-je détecter dans la méthode Dispose si le code quitte en utilisant bloc volontairement ou à la suite d'une exception?

Répondre

1

Vous ne pouvez pas, au meilleur de ma connaissance. Pensez à changer Foo à une méthode qui prend le « corps » pour envelopper et exécuter comme lambda:

Foo(f => { 
    // do whatever 
}); 

Ensuite, votre mise en œuvre de Foo peut envelopper l'appel en try/catch pour détecter des exceptions et faire ce que vous voulez faire (puis relancez en utilisant throw;).

+0

C'est une bonne idée, merci. – AngryHacker

0

Vous ne devriez pas faire cela - et je ne peux pas imaginer un moyen de le faire.

L'idée principale de l'implémentation IDisposable est de s'assurer que les ressources sont libérées lors de la destruction de l'objet. Maintenant, l'idée principale de la construction using est de s'assurer qu'après cela, toutes les ressources utilisées par l'objet sont libérées. Donc, vous ne devriez pas dépendre de pourquoi l'objet est disposé pour effectuer cette opération. Si vous le faites, vous devriez revoir votre conception.

+0

Il existe une école de pensée qui considère 'IDisposable' et' using 'comme des mécanismes RAII à usage général, utilisables pour plus que libérer des ressources. Dans ce scénario, il est parfaitement normal de faire la distinction entre les scénarios «en cas de succès» et «en cas d'échec» - p. en D, il y a un support de langage de première classe pour cela, avec 'scope (success)' et 'scope (failure)'; en C++, on utiliserait 'std :: uncaught_exception()'; etc. –

+0

@Bruno. Oui, ce que Pavel a dit. Le mot clé using est absolument génial pour la portée et l'utiliser en combinaison avec Dispose est très puissant. – AngryHacker

+0

Si la routine Dispose ne peut pas rétablir les choses dans un état acceptable, elle doit déclencher une exception. À ce stade, l'exception d'élimination et l'exception d'origine doivent toutes deux être propagées (le plus proprement possible en plaçant l'exception d'origine en tant qu'exception InnerException de l'exception d'élimination). Pour que cela fonctionne, cependant, il doit y avoir un moyen pour l'éliminateur d'obtenir l'exception en suspens. – supercat