Les directives de programmation .NET indiquent que nous ne devrions pas attraper des exceptions générales. Je suppose que le code suivant n'est pas très bon à cause de la capture de type d'exception générale: dans le code suivant, j'atteigne des exceptions particulières mais pas toutes et je ressens tous l'exception dans L'affaire est différente des exceptions non génériques. Toutefois, la fonction "CreateInstance" peut lancer de nombreuses exceptions (argumentnullextance, ArgumentException, notsupportedException, TargeCeVocationException, MéthyAccessException, MemberCessException, InvalidCompacteXception, manquanteMethodexception, Comexception, Typeloadexception). P> est-il acceptable d'attraper toutes les autres exceptions individuelles? Ou y a-t-il une meilleure façon? P> private object CreateObject(string classname)
{
object obj = null;
if (!string.IsNullOrEmpty(classname))
{
try
{
System.Type oType = System.Type.GetTypeFromProgID(customClass);
obj = System.Activator.CreateInstance(oType);
}
catch (NotSupportedException ex)
{
Log.Error("...." + ex.Message);
}
catch (TargetInvocationException ex)
{
Log.Error("...." + ex.Message);
}
catch (COMException ex)
{
Log.Error("...." + ex.Message);
}
catch (TypeLoadException ex)
{
Log.Error("...." + ex.Message);
}
catch (InvalidComObjectException ex)
{
Log.Error("...." + ex.Message);
}
catch (Exception ex)
{
Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message);
throw;
}
}
return obj;
}
7 Réponses :
Il est tout à fait acceptable d'attraper des exceptions générales dans .NET 2+ du cadre. P>
- Edit p>
La seule raison pour laquelle vous ne le feriez pas, c'est si vous pouvez faire quelque chose de différent avec une exception différente. Si vous envisagez de les manipuler tous les mêmes, attrapez simplement le général (ou spécifique que vous êtes après et laissez autre chose monter). P>
Je suis d'accord. Parfois, je sens que nous prenons cela pas attraper une exception générale aux extrêmes.
Je ne suis pas d'accord. Cela laissera votre application dans un état exceptionnel. Vous ne devez gérer que des exceptions que vous pouvez faire quelque chose. Il suffit de vous connecter et de passer à autre chose est une mauvaise idée.
@ justin.m.chase: c'est une position très étrange. Donc, à tout moment, votre application se bloque, vous préférez avoir vos utilisateurs voir la page d'erreur générale .NET au lieu de votre propre?
La journalisation et le déplacement sont une mauvaise idée pour des exceptions inconnues, car vous ne savez pas à quel point l'exception est mauvaise. Par exemple, que se passe-t-il si vous frappez une exception exceptionnelle? Vous ne devriez pas simplement enregistrer cette erreur et passer à autre chose. Le programme devrait arrêter de courir. Il est préférable de "échouer vite" que d'essayer de conserver un programme instable en cours d'exécution. martinfowler.com/eeesoftware/failfast.pdf
@Phil: Vous n'avez pas compris ma réponse. Je vous suggère de prendre plus de soins dans le futur.
L'impression que je reçois, c'est que vous dites que c'est bien d'attraper un système général.Exception, de la gérer et de poursuivre l'exécution. Correct?
@Phil: Non, pas correct. Il se demandait s'il y a une raison particulière de ne pas attraper des exceptions générales. Je dis que c'est bien, si tu peux faire quelque chose avec ça. C'est-à-dire, logez ou sortez gracieusement, ou tout ce que vous jugez approprié. Je ne dis pas que vous attrapez des exceptions et ignorez-les, laissant ainsi votre application se poursuivre comme si rien ne s'est trompé. Attraper trop d'exceptions spécifiques est fausse. Attraper des exceptions spécifiques est clairement correcte (par exemple, Filenotfound, tout ce que vous pouvez imaginer).
@Non je serais d'accord avec ça. Cependant "si vous envisagez de les manipuler tous les mêmes, il suffit d'attraper le général" pourrait être interprété par un programmeur inexpérimenté qu'il est correct d'attraper un système général.Exception, de faire quelque chose, puis de poursuivre l'exécution. Il serait peut-être bon de préciser que si vous ne savez pas quel type d'erreur vous manipulez, vous feriez mieux de retirez-le ou de la sortie.
Topic Starter ne fait pas exactement la même chose. S'il met la capture générale, il devrait avoir si (ex est ... ou ex est ...) {} else {lancer;}
Je pense qu'il est correct d'attraper toutes les exceptions pour intercepter un problème et afficher un message amical à un utilisateur plutôt que de la sortie effrayante de la pile. P>
Pour aussi longtemps que vous n'invalez pas simplement des exceptions, mais connectez-les et réagissez-leur de manière appropriée en arrière-plan. P>
Si vous voulez faire quelque chose de spécial avec un type d'exception différent, attrapez-le dans un bloc de capture séparé. Sinon, il n'a pas de sens de les enregistrer séparément. P>
Il n'y a pas une règle rigide que nous ne devrions pas utiliser d'exception générale, mais la ligne directrice indique que chaque fois que nous avons la possibilité de gérer un type d'exception spécifique, nous ne devrions pas aller pour une exception générique. P>
Si nous sommes sûrs que toute l'exception sera manipulée de la même manière, utilisez une exception générique autrement aller pour chaque exception spécifique et générique devrait finir par une certaine exception inconnue. P>
Et parfois dans votre application, toute exception se produit non traitée dans le code due à une manipulation spécifique des exceptions, votre application peut aller pour crash .. p>
Donc, la meilleure approche est donc gérer toute exception spécifique, puis donner un coin à une exception générique également afin que l'application reste stable sans crash .. p>
et la présente exception générique indésirable peut être signalée ou enregistrée quelque part pour une nouvelle version d'amélioration de l'application. P>
En règle générale, vous ne devriez pas attraper des exceptions à moins que:
Vous avez une exception spécifique que vous pouvez gérer et faire quelque chose. Cependant, dans ce cas, vous devriez toujours vérifier si vous ne devriez pas essayer de prendre votre compte et d'éviter l'exception en premier lieu. P> li>
Vous êtes au niveau supérieur d'une application (par exemple l'interface utilisateur) et ne souhaitez pas que le comportement par défaut soit présenté à l'utilisateur. Par exemple, vous voudrez peut-être une boîte de dialogue d'erreur avec un message "s'il vous plaît envoyez-nous votre journal" Message de style. P> LI>
Vous rejetez l'exception après avoir affaire à elle en quelque sorte, par exemple si vous réduisez une transaction DB. P> LI> ol>
Dans cet exemple, pourquoi attrapez-vous tous ces types différents? Il me semble que votre code peut simplement être: P>
try { System.Type oType = System.Type.GetTypeFromProgID(customClass); return System.Activator.CreateInstance(oType); } catch (COMException cex) { //deal with special case: return LoadUnmanaged(); } catch (Exception ex) { Log.Error("...." + ex.Message); //the generic catch is always fine if you then do this: throw; }
J'attrape tous ces types d'exceptions différents car ils peuvent se produire (par exemple, l'utilisation peut transmettre un nom de classe qui n'est pas supporté ou non enregistré correctement) et, dans ce cas, il n'y a pas de bon moyen de vérifier à l'avance pour une exception (comme je peux Vérifiez que ArgumentNulxception).
Je suis sûr qu'ils peuvent tous arriver, mais à moins que vous ne fassiez quelque chose de spécifique pour ce type d'exception, vous ferez mieux d'attraper l'exception générale code> et de le jeter sur up.
Cette réponse est parfaitement correcte. La clé est que vous lancez l'exception générale vers le haut et non pas la plus avaler.
Il est considéré comme une mauvaise pratique pour attraper habituellement la base Le danger dans le traitement de toutes les erreurs de la même manière, est-ce que cela implique que vous ne vous souciez pas de la gravité de l'erreur ou de la manière dont vous risquez de résoudre l'erreur. 99% du temps, lorsque je vois le code Votre exemple de journalisation d'erreur indique la bonne façon d'utiliser la base exception code> lors de la gestion des erreurs de traitement, car cela montre un manque potentiel de compréhension quant à ce que vous manipulez réellement. Lorsque vous voyez un bloc de code de code
exception code> ce qu'il se lit est: "Si quelque chose ne va pas ici, faites-le", où que quelque chose puisse aller d'un
NullReferenceException code> à un < Code> OutofMemoryException code>. P>
attrape (exception ex) code>, il est immédiatement suivi d'un code qui avale l'exception, ce qui ne donne aucune idée en réalité pourquoi les déclarations ont échoué. Ugh. P>
Exception code>, dans une situation lorsque vous souhaitez vraiment traiter toutes les exceptions, généralement au niveau supérieur d'une application pour empêcher l'application se terminant dans un désordre laids. P>
Je suis d'accord avec la réponse de Keith. Le vrai problème avec les deux exemples de code est qu'ils peuvent renvoyer null. Vous avez une méthode appelée CreateObject qui renvoie une instance d'objet de type. Cette méthode a échoué pour une raison quelconque, telle qu'une interpréception. Les deux exemples de code retourneront alors NULL. Le code d'appel est maintenant responsable de la vérification du résultat vs NULL, ou il lancera une nullreferenceException. P>
citant Directives de conception-cadre 2nd ed. : p>
Si un membre ne peut pas réussir ce qu'il est conçu pour faire, il devrait être considéré comme une défaillance d'exécution, et une exception doit être lancée. P> blockQuote>
Cela n'a pas fait ce que son nom suggère. Lancer! P>
Le code de Keith est bien; C'est bon de se connecter à l'exception et à Retirhow. P>
Il s'agit d'une méthode privée, de sorte que les directives de conception ne s'appliquent pas. Je les appliquerais toujours ici, cependant, pourquoi, pourquoi joncher votre code avec "si (résultat == null)" lorsque vous pouvez utiliser la manutention des exceptions à la place? P>
Il est parfois utile d'avoir une méthode qui essaiera de créer un objet, mais de retourner null s'il ne peut pas; C'est souvent une bonne idée, cependant, de donner à la méthode un nom qui suggère que c'est ce qu'il va faire. Microsoft préfère que de telles routines retourne un booléen pour réussir / échec et avoir en tant que paramètre BYREF une variable de référence d'objet pour stocker le nouvel objet, mais je préfère retourner la valeur ou la null, car elle permet de définir une nouvelle variable dans la déclaration qui tente de créer l'instance.
@supercat: Ce qui irait bien si nous pouvions faire confiance aux autres développeurs (et nous-mêmes) pour toujours vérifier si la valeur renvoyée est null ...
Si vous appelez une fonction appelée trygegefoo sans envisager que cela pourrait échouer, ils méritent de ce qu'ils obtiennent. Ils pouvaient encore plus facilement ignorer la valeur de retour (Succès / Drapeau de défaillance) à partir d'une méthode MS-Modèle "trygetfoo". La version MS-Modèle a une fonctionnalité dans certaines situations pouvant être une bonne ou une mauvaise chose: il est possible que la fonction de jeter une exception mais définit toujours la variable passée à quelque chose avant qu'elle ne le fait. Cela peut être bon si la variable est idissible, mais pourrait provoquer une confusion si le code de retour de la méthode de création est ignoré.
Dupliquer de: Stackoverflow.com/questions/204814/...