130 votes

Pourquoi ne devons-nous pas lancer ces exceptions?

Je suis tombé sur cette page MSDN que les états:

Ne jetez pas de Système.Exception, Système.SystemException, Système.NullReferenceException, ou d'un Système.IndexOutOfRangeException intentionnellement à partir de votre propre code source.

Malheureusement, il ne prend pas la peine d'expliquer pourquoi. Je peux deviner les raisons, mais j'espère que quelqu'un de plus digne de foi sur le sujet pourrait donner leurs opinions.

Les deux premiers font certains sens évident, mais les deux derniers semblent comme ceux que vous voulez employer (et en fait, ce que j'ai).

De plus, ce sont les seules exceptions il faut éviter? Si il en existe d'autres, quels sont-ils et pourquoi devraient-ils, eux aussi, être évité?

110voto

poke Points 64398

Exception est le type de base pour toutes les exceptions, et en tant que tel terriblement imprécis. Vous ne devriez jamais lever cette exception parce que simplement, il ne contient pas toutes les informations utiles. Code appelant de chasse pour les exceptions ne pouvais pas lever l'ambiguïté de l'intentionnellement la levée d'une exception (à partir de votre logique) de l'autre système d'exceptions qui sont entièrement non désirées et le point de véritables défauts.

La même raison vaut également pour SystemException. Si vous regardez la liste des types dérivés, vous pouvez voir un grand nombre d'autres exceptions très différentes de la sémantique.

NullReferenceException et IndexOutOfRangeException sont d'un genre différent. Maintenant ce sont de très exceptions spécifiques, afin de les jeter à la pourrait être bien. Cependant, vous ne voulez pas pour jeter ces derniers, car ils signifient qu'il y a quelques erreurs dans votre logique. Par exemple la référence nulle exception signifie que vous essayez d'accéder à un membre d'un objet qui est - null. Si c'est une possibilité dans votre code, alors vous devriez toujours explicitement vérifiez null et jeter un plus utile d'exception (par exemple, ArgumentNullException). De même, IndexOutOfRangeExceptions se produire lorsque vous accédez à un index non valide (sur les tableaux-et non pas des listes). Vous devriez toujours vous assurer que vous ne le faites pas, en premier lieu, et de vérifier les limites, par exemple, une matrice de première.

Il y a quelques exceptions, comme ces deux-là, par exemple, InvalidCastException ou DivideByZeroException, qui sont jetés pour certaines fautes dans votre code et signifie généralement que vous faites quelque chose de mal ou que vous n'êtes pas vérifier pour certaines valeurs non valides en premier. En jetant sciemment à partir de votre code, vous êtes simplement en rendant plus difficile pour le code d'appel afin de déterminer s'ils ont été jetés en raison des quelques la faute dans le code, ou juste parce que vous avez décidé de les réutiliser pour quelque chose dans votre mise en œuvre.

Bien sûr, il existe quelques exceptions (hah) à ces règles. Si vous êtes à la construction de quelque chose qui peut provoquer une exception qui correspond exactement à un existant, alors n'hésitez pas à l'utiliser, surtout si vous essayez de faire correspondre un comportement intégré. Assurez-vous de choisir un très spécifique type d'exception alors.

Toutefois, en général, à moins de trouver une (des) exception qui remplit votre besoin, vous devez toujours envisager de créer vos propres types exception pour les exceptions. Surtout quand vous écrivez le code de la bibliothèque, cela peut être très utile pour séparer l'exception des sources.

38voto

Marc Gravell Points 482669

Je soupçonne que l'objectif des 2 dernières est d'empêcher la confusion avec des exceptions qui ont une espérance de sens. Cependant, je suis d'avis que, si vous êtes à la préservation de l'intention exacte de l'exception: c'est le correct throw. Par exemple, si vous écrivez une collection personnalisée, il semble tout à fait raisonnable d'utiliser IndexOutOfRangeException - plus claires et plus précises, de l'OMI, que ArgumentOutOfRangeException. Et tandis que l' List<T> pourrait choisir celui-ci, il y a au moins de 41 places (avec l'aimable autorisation de réflecteur) dans la BCL (pas y compris les tableaux) qui se jettent sur mesure IndexOutOfRangeException - dont aucun n'est "bas niveau" assez pour mériter exemption spéciale. Donc oui, je pense que vous pouvez à juste titre valoir que cette directive est stupide. De même, NullReferenceException est plutôt utile dans les méthodes d'extension - si vous souhaitez conserver la sémantique que:

obj.SomeMethod(); // this is actually an extension method

jette un NullReferenceException lorsque obj est null.

8voto

DavidRR Points 2211

Comme vous le soulignez, dans l'article de la Création et de lever des Exceptions (C# Programmming Guide) sous la rubrique Choses à Éviter Lors de la levée d'Exceptions, Microsoft n'a en effet de liste System.IndexOutOfRangeException comme un type d'exception qui ne doivent pas être jetés intentionnellement à partir de votre propre code source.

En revanche, dans l'article de le jeter (Référence C#), Microsoft semble ne pas respecter ses propres lignes directrices. Voici une méthode que Microsoft a inclus dans son exemple:

static int GetNumber(int index)
{
    int[] nums = { 300, 600, 900 };
    if (index > nums.Length)
    {
        throw new IndexOutOfRangeException();
    }
    return nums[index];
}

Ainsi, Microsoft lui-même n'est pas conforme car il montre la projection d' IndexOutOfRangeException dans sa documentation throw!

Ce qui m'amène à penser que, au moins pour le cas de l' IndexOutOfRangeException, il peut y avoir des cas où ce type d'exception peut être levée par le programmeur et être considéré comme une pratique acceptable.

1voto

Bellash Points 1330

Quand j'ai lu votre question, je me suis demandé dans quelles conditions on aurait envie de jeter l'exception des types d' NullReferenceException, InvalidCastException ou ArgumentOutOfRangeException.

À mon avis, lors de la rencontre d'un de ces types d'exception, je (le développeur) se sentent concernés par l'alerte dans le sens que le compilateur me parle. Donc, vous permettant de vous (le développeur) pour lancer de tels types d'exception est équivalent à (le compilateur) de la vente de la responsabilité. Par exemple, ce qui suggère que le compilateur doit maintenant permettre au développeur de décider si un objet est - null. Mais cette détermination devrait vraiment être le travail du compilateur.

PS: Depuis 2003, j'ai développé mes propres exceptions afin que je puisse les jeter comme je le souhaite. Je pense que c'est considéré comme une meilleure pratique de le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X