7
votes

C # - Retire une exception sans le régler à une variable

Comme vous le savez tous probablement, attraper et re-jeter une exception en C # de cette façon est diabolique, car il détruit la trace de la pile: xxx pré>

la bonne façon de réapprocher Exception sans perdre la trace de la pile est ceci: p> xxx pré>

Le seul problème est que je reçois beaucoup d'avertissements de compilation: "La variable 'ex' est déclarée mais jamais utilisée ". Si vous en avez beaucoup, un avertissement utile peut être caché dans les ordures. Donc, c'est ce que j'ai fait: p>

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException)
{
    throw;
}
catch(AnotherException ex)
{
    //handle it
}


4 commentaires

ERM, pourquoi dans le monde jetez-vous une exception, attrapez-le et retirez-le Tout de la même méthode ?


@Cody Grey - Je devine juste, ici, mais (donnant au profit du doute) Je suppose qu'il vient de fournir un exemple de code pour montrer qu'il comprend la différence entre lancer et et lancer ex . Non pas qu'il générait réellement une exception dans une méthode qui attrape cette exception, puis le retire. J'espère quand même.


@Cody Grey, @alleng a raison, c'est juste un exemple simple pour montrer ce que j'essaie d'atteindre, pas un vrai code


D'accord, bien. C'est ce que j'espérais, et pourquoi j'ai posté cela comme un commentaire plutôt qu'une réponse. Vous seriez surpris du genre de folie que je vois les gens à faire ici avec des exceptions / attraper.


6 Réponses :


5
votes

Si vous ne faites rien avec DummyException code> dans le bloc CODE> CATCH CODE> Bloc (que vous ne pouvez pas, car vous ne l'avez pas donné un identifiant), pourquoi pas Débarrassez-vous du essayer / attraper code> bloc entièrement? Par exemple, faites cela:

throw new DummyException();


6 commentaires

La raison pour laquelle vous pourrez attraper DummyException spécifiquement et simplement le jeter est que vous pourriez le gérer à un niveau plus élevé (plus proche du UI). Et try / attrape vous permet à A) incluent un enfin si vous en avez besoin d'un, et B) pour attraper plusieurs exceptions.


@Alleng Il est correct d'avoir un essayer / enfin qui n'a pas de attrape blocs. Je ne sais pas avec certitude, mais je ne serais pas surpris si le compilateur a optimisé sa prise.


@Mattgree: True: Mais vous avez toujours besoin du essayer . Je faisais référence à la suggestion de "se débarrasser du try / attraper bloc entièrement" que vous ne voudriez pas faire - puisque vous avez au moins besoin du essayer .


@Alleng Bon points à prendre en compte; Ma réponse a été basée sur l'exemple de l'OP (aucun autre Catch blocs et non enfin ).


@Donut, j'ai donné cet exemple parce que cela montre mon problème - n'utilise pas la variable si je vais à ressusion, ce qui me donne un avertissement de compilateur. Dans un code réel, j'aurais plusieurs captures et / ou un blocage enfin


@Andre assez équitable, bien que je dirais que le passage de l'exception non confondu de la pile a quelques inconvénients (c'est-à-dire créer plusieurs points de sortie de la fonction).



8
votes

Il n'y a pas d'inconvénient à cela. Vous dites simplement au compilateur "Je prévois d'attraper cette exception, mais je n'ai pas besoin d'une référence à l'exception réelle", cela n'affecte pas la manière dont les choses sont lancées ou la façon dont les exceptions fonctionnent. Votre dernier exemple est le moyen idéal de faire ce que vous voulez, cependant, si vous allez simplement aller immédiatement à lancer; avec rien d'autre dans le bloc, alors pourquoi attraper le tout?


0 commentaires

1
votes

Pourquoi attraper si vous allez simplement rejeter? Quoi qu'il en soit, vous voudrez peut-être jeter un coup d'œil à cette discussion précédente. Bien que non identique une grande partie de ce qui est discuté est pertinent:

Jetez VS Rethrow: Même résultat?


1 commentaires

Merci pour le lien. Répondre à votre question, le code n'est qu'un exemple, je peux re-jeter un type d'exception mais pas d'autres (si vous avez plusieurs blocs de capture)



1
votes

lance réellement une exception en utilisant "lancer;" est un .NET Meilleure pratique , car il préserve la trace de la pile d'exception.

Lancer des exceptions en utilisant "Three Ex;" est considéré comme une pire pratique , car elle perd la trace d'originale de la pile et doit être évitée.


1 commentaires

Il affirme réellement que dans la question ... :)



9
votes

J'aimerais savoir s'il y a un inconvénient de ré-jeter une exception qui n'est pas définie sur une variable.

Non, il n'y a pas de pas du tout. Une variable n'est nécessaire que si vous souhaitez faire référence à l'exception dans votre code, mais que vous n'avez pas besoin de le faire avec une instruction , vous n'avez pas besoin d'une variable du tout.

Et vous avez exactement la bonne idée en essayant d'éliminer les avertissements du compilateur «bruyant». Ils ont tendance à enterrer des erreurs importantes que vous les voulez-vous corriger et d'obtenir une construction propre est toujours importante. La meilleure solution consiste simplement à réécrire le code pour utiliser un paramètre Catch .

Cependant, soyez conscient que dans 82% des cas que je vois * , c'est une erreur d'écrire du code qui utilise lancer du tout. Vous ne devriez généralement pas attraper des exceptions que vous ne savez pas comment gérer et votre seule stratégie «de manutention» prévue est de repousser. Il y a des cas où, même en utilisant lancer , peut réinitialiser la pile d'appels, ce qui vous oblige à perdre d'importantes informations de débogage. Il existe également de meilleures alternatives pour la journalisation des exceptions à attraper / retirent. Vous pouvez trouver plus d'informations dans les réponses à ces questions:


2 commentaires

Merci pour votre réponse, c'est exactement ce que je cherchais. J'ai déjà fait beaucoup d'erreurs dans la manipulation des exceptions, mais je pense que je suis un peu mieux avec ça maintenant. Je les manipulez généralement à l'intérieur de la méthode ou d'une couche en évitant que cela va trop de couches. Je jette habituellement une exception décochée qui bulle et donne un message d'erreur générique à l'utilisateur. Est-ce une mauvaise pratique?


@andre: Il n'y a absolument rien de mal à laisser des exceptions à la bulle et à les manipuler tous dans un endroit central. La règle à garder à l'esprit est que vous ne devriez pas utiliser des exceptions pour le contrôle des flux. Mais il n'y a rien de mal à jeter une exception dans le code de niveau bas et à montrer à l'utilisateur un message d'erreur supérieur à la pile dans le code de l'interface utilisateur. Vous devrez probablement poster un réel échantillon de code pour que je soit plus spécifique. Mais vous devriez lire Microsoft's Meilleures pratiques pour la manipulation d'exceptions pour quelques conseils généraux .



1
votes

Pourquoi attraper et retirh comme ça? Pourquoi les gens doivent-ils toujours supposer qu'ils savent chaque cas? Réponse: transactions de base de données.

Si vous avez une meilleure façon de le faire, veuillez parler du Dr Proton, aucune infraction prise. Gardez à l'esprit qu'il existe de nombreux systèmes de base de données différents utilisés, mais la plupart d'entre eux supportent le contrôle des transactions (commencements / commit / Rollback) et ont des interfaces C #. P>

pseudocode (cas simplifié): P): P >

try
{
   db.beginTrans();

   db.doStuff();

   db.doOtherStuff();

   db.commitTrans();
}
catch
{
  db.rollbackTrans();
  throw;
}


1 commentaires

Voici un message que j'ai trouvé qui offre une idée et une solution possible: weblogs.asp.net/fmarguerie/archive/2008/01/02/...