10
votes

Attraper une exception avec condition

note: je suis très heureux de vous dire que les filtres d'exception sont maintenant dans la langue c # 6.0.

C'est une expérience de pensée, je m'intéresse à votre avis: ça fait sens pour vous? Savez-vous si quelque chose de similaire a déjà été proposé pour la langue de programmation C #? Je ne saurais même pas où envoyer une telle proposition ...

L'idée est introduisant des éléments de syntaxe pour attraper une exception uniquement si elle remplit une certaine condition.

Un exemple d'utilisation exemple est lorsque vous travaillez avec com Interop: tout lance toujours un Comexception . Le code d'erreur distinctif réel est contenu dans son message.

Alors qu'en est-il (proposition 1): xxx

qui se traduit par: < Pré> xxx

Les cas similaires sont: SOAPException , xmlexception ...


Un autre scénario est lorsque des exceptions sont lorsque des exceptions sont Enveloppé comme des exceptions internes dans une exception générale et la logique capture doit dépendre de l'exception interne.

dire que nous avons une API qui envoie des exceptions comme ceci: attrape (NumberFormatException ex) {lancer une nouvelle nouvelle entreprise (ex)} .

Qu'en est-il de (proposition 2a): xxx

qui se traduit par: < / p> xxx

ou (2b): xxx

qui se traduit par: < Pré> xxx

dans Ce cas (originaire de Java) pourrait ressembler à (2c): xxx


6 commentaires

La barre est élevée pour les nouvelles fonctionnalités linguistiques en C #. Et cette fonctionnalité ne ajoute rien que vous ne pouviez pas déjà faire facilement à mon avis.


@ 0xa3: Non, c'est juste du sucre syntaxique. Mais cela extrapole en quelque sorte les idées derrière Linq (au moins proposition 1).


Je pense que vous pouvez le poster sur Microsoft Connect où vous pouvez demander cela comme une fonctionnalité.


@chiccodoro: Ce n'est pas du sucre syntaxique. Le comportement est différent. Voir ( blogs.msdn.com/b/clrteam/archive/2009/08/25/... ) Pour une explication détaillée sur la manière dont les travaux de manutention d'exception à deux transmettes dans CLR.


@Pratik: C'est un point intéressant. D'autre part, la spécification .NET garantit-elle un ordre spécifique dans lequel les blocs finissent par enfin sont exécutés? Jusqu'à présent, je pensais non, alors un programmeur ne devrait jamais compter sur un certain ordre de toute façon. En le mettant de cette façon, le comportement spécifié est égal, il n'y a que des différences non spécifiées en dessous ...


Transformé en wiki communautaire, pensez que c'est plus approprié.


7 Réponses :


4
votes

Exceptions et types sont étroitement liés. Si vous souhaitez distinguer deux types d'exceptions distincts, vous devez effectuer deux types d'exception. Dans votre exemple, vous auriez une interprétation COM800706BAEXException et une COM80010001Exception.

Maintenant, il n'est pas toujours possible ou réalisable, par exemple si le système sous-jacent utilise des codes d'erreur au lieu d'exceptions. Dans ce cas, votre méthode peut être utile. Cependant, cette caractéristique linguistique serait facilement mal utilisée. Par exemple, vous pouvez faire des erreurs de manipulation comme ceci, ce qui n'est pas sécurisé: xxx

Si vous souhaitez vérifier l'exception interne d'une exception, vous faites l'erreur. Manipulation du mauvais niveau. L'idée est qu'une méthode jette une exception généralisée pour résumer l'appelant du fonctionnement intérieur de la méthode. Si vous dépendez d'une exception interne, vous êtes étroitement couplé à la mise en œuvre de la méthode. C'est mauvais.

soit une exception distincte généralisée doit être levée, ou la manipulation des erreurs doit être déplacée à l'intérieur de la méthode.


1 commentaires

Comme vous le dites, Ceci n'est pas toujours possible : Interop lance toujours Comexception . Je suis le client de l'Interop, pas le programmeur ...



8
votes

vb.net a cette fonctionnalité de filtre d'exception comme indiqué ci-dessous xxx

de sorte que ceci est supporté par le CLR mais la fonctionnalité n'est pas exposée en C #

supposément f # A cette fonctionnalité aussi, mais je ne sais pas grand chose à propos de F # pour montrer l'exemple.


7 commentaires

+1 fantastique! Étant donné que vb.net a cette fonctionnalité, je ne pense pas que ce soit un travail difficile pour l'équipe DEV d'ajouter cette fonctionnalité à C #.


Mais alors probablement pas une demande inconnue et que d'autres l'ont dit, cela ne vous donne pas le pouvoir de faire quoi que ce soit sur lequel vous ne pouvez pas faire. Pour être émoussé, cela ne simplifie même pas beaucoup les choses. En tant que tel, le coût de l'ajout (et des manhours ou des minutes pour changer la syntaxe n'est qu'une petite partie de celle-ci, Google pour Eric Lippert et vous trouverez probablement certaines de ses listes de choses qui coûtent au cours d'une modification) est probablement Trop grand pour ce qui constitue essentiellement une syntaxe différente de faire ce que vous pouvez déjà faire. Donc non, probablement pas difficile, mais probablement ne sera probablement pas fait non plus.


Sucre syntaxique, cela n'est pas pris en charge au niveau du CLR.


Les filtres d'exception sont puissants car le filtre est évalué avant que le bloc de capture soit exécuté. Mais cela a des effets secondaires surprenants si vous ne faites pas attention. Fondamentalement, le filtre et la vérification à l'intérieur d'un bloc d'essai diffère de manière significative pour l'ordre d'évaluation. [Voir] ( blogs.msdn.com/b/clrteam/archive/2009/08/25/... )


@Leppie, il est définitivement pris en charge au niveau CLR et IL. Vb.net et f # l'a. Cochez une explication détaillée de la publication de blog référencée dans mon commentaire précédent sur la façon dont la manutention des exceptions fonctionne en deux Pass par CLR.


@Pratik: Merci! Je n'ai jamais su comment utiliser ça. Maintenant, j'ai un exemple de vb.net. Semble assez intéressant de l'enquête initiale :)


@Pratik: Vous devriez inclure ce lien dans votre réponse, par exemple. [est pris en charge par le CLR] [1] [1]: blogs.msdn.com/b/clrteam/archive/2009/08/25/...



2
votes

Pourquoi faire cuire quelque chose dans la langue qui est trivial à faire quand même?

Proposition 1 est facilement adressée à une instruction de commutation ciblée à l'intérieur de la capture - de cette façon, vous pouvez gérer les exceptions de la COM que vous souhaitez et rapprochez tout ce que vous ne voulez pas traiter. < / p>

Le problème avec Proposition 2 est que la pile d'exception pourrait être arbitrairement profonde et pourrait (ou la volonté) contient:

  • Des instances imbriquées multiples du même type d'exception - que l'une condition de votre syntaxe de requête?

  • exceptions différentes qui dérivent de la même exception de base * - si votre syntaxe de requête spécifie l'une des exceptions de base de niveau inférieur, cela pourrait correspondre à un tas d'exceptions de niveau supérieur dans la pile, lequel est vous cherchez à traiter?

    La plupart du temps lorsque vous êtes itération de la pile d'exception, vous ne voudrez pas récupérer l'exception à mi-chemin de la pile, vous marcherez à la place de la pile d'exception et obtenez le tout premier à des fins de journalisation. Le reste du temps que vous vous souciez que de la dernière exception (extérieure). Personnellement, je ne peux pas me rappeler un temps où j'avais besoin de prise de manière programmatique / gérer une exception qui a été enterrée quelque part au milieu de la pile, elle a toujours été la première, la dernière ou toutes. < / p>

    * Ne tenant compte du fait que toutes les exceptions proviennent de System.Exception - je signentais plus dans les lignes de myBaseException que toutes vos exceptions personnalisées dérivent de.


0 commentaires

1
votes

Je ne suis pas sûr que j'aime beaucoup ça. Tout d'abord, cela ressemblait à une idée vraiment soignée, mais je suis ensuite venu de penser que si vous ajoutez du sucre syntaxique pour ce genre de chose, les gens abuseront probablement des exceptions lorsqu'un code de statut est plus approprié.

Comme quelques personnes ont Déjà signalé, c'est déjà dans VB, mais vous pourrez facilement faire quelque chose de similaire dans C #: xxx

donc, il ne s'agit que de sucre syntaxique.

La chose à propos des exceptions est que (comme souvent discutée sur ce site), ils violent la structure séquentielle de votre programme, en sautant potentiellement beaucoup de code et en faisant apparaître la pile lorsque vous ne le souhaitez vraiment pas. C'est pourquoi je ne pense pas qu'ils soient bons pour tout ce que des conditions très exceptionnelles, et si vous êtes vraiment peut manipuler ces conditions, il devrait être un peu douloureux (essayez {} Catch {Si ( ..)}, etc.), afin que les gens ne soient pas susceptibles d'utiliser des exceptions pour plus de ces conditions exceptionnelles.


0 commentaires

2
votes

Je pense que c'est assez délicat et déroutant:

Et si votre condition d'exception jette une exception aussi? Où et comment cette nouvelle exception devrait-elle être traitée?

  • un essai / attrape autour d'un bloc de capture? MEH ..
  • Laissez les autres blocs de capture manipulés cette exception: Stackoverflows YAY :)

1 commentaires

Out of Memory Exception -> Essayez de formater une chaîne à imprimer à la console -> Exception de la mémoire -> Overflow de pile ...



26
votes

Selon le Testez-la-catch C # Référence pour Visual Studio 2015 RC Ceci est maintenant implémenté:

Catch (ArgumentException e) when (e.ParamName == "…")
{
}


1 commentaires

Ils ont changé si pour attraper (exception e) quand (E.ParamName == "...)



2
votes

Depuis C # 7.0 Ce genre de choses déjà soutenu. ici est une référence complète. Voici un extrait de code.

    try
    {
        SomeOperationThatThrowsException();
    }
    catch(TheFilteredException ex ) when (ex.ErrorCode==123)
    {
        DoSomethingWhenExceptionThrown();
    }


0 commentaires