Je sais que c'est une vieille question, mais je vais répondre parce que j'ai pas d'accord avec toutes les réponses ici.
Maintenant, je suis d'accord que la plupart du temps, vous voulez faire un plain throw
, afin de préserver autant d'informations que possible au sujet de ce qui s'est passé, ou si vous voulez lancer une nouvelle exception qui peut contenir qu'un intérieur d'exception, ou pas, en fonction de la probabilité que vous voulez savoir sur les événements intérieurs qui l'a causé.
Il y a cependant une exception. Il y a plusieurs cas où une méthode d'appel à une autre méthode et une condition qui provoque une exception à l'intérieur de l'appel doit être considérée de la même exception à l'extérieur de l'appel.
Un exemple est une collection spécialisée en œuvre par l'utilisation d'une autre collection. Disons que c'est un DistinctList<T>
qui encapsule une List<T>
mais refuse les éléments en double.
Si quelqu'un a appelé l' ICollection<T>.CopyTo
sur votre classe de collection, il pourrait juste être un droit d'appel à l' CopyTo
sur l'intérieure de la collection (si par exemple, toute la logique personnalisée uniquement appliqué à ajouter à la collection, ou de la constitution). Maintenant, les conditions dans lesquelles cet appel jeter sont exactement les mêmes conditions dans lesquelles votre collection doit jeter pour correspondre à la documentation de l' ICollection<T>.CopyTo
.
Maintenant, vous pourriez tout simplement pas attraper l'exception à tous, et de le laisser passer à travers. Ici, si l'utilisateur obtient une exception à partir d' List<T>
lorsqu'ils ont été d'appeler quelque chose sur un DistinctList<T>
. Pas la fin du monde, mais vous pouvez masquer les détails d'implémentation.
Ou vous pourriez faire votre propre vérification:
public CopyTo(T[] array, int arrayIndex)
{
if(array == null)
throw new ArgumentNullException("array");
if(arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex", "Array Index must be zero or greater.");
if(Count > array.Length + arrayIndex)
throw new ArgumentException("Not enough room in array to copy elements starting at index given.");
_innerList.CopyTo(array, arrayIndex);
}
Ce n'est pas le pire de code parce que c'est passe-partout et l'on peut probablement juste de copier à partir d'une autre mise en œuvre de l' CopyTo
où il n'était pas un simple pass-through et nous avons eu à mettre en œuvre nous-mêmes. Pourtant, c'est inutilement de répéter la même exacte des contrôles qui vont être effectuées en _innerList.CopyTo(array, arrayIndex)
, de sorte que la seule chose qu'il a ajouté à notre code est 6 lignes où il pourrait y avoir un bug.
Nous avons pu vérifier et wrap:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentNullException ane)
{
throw new ArgumentNullException("array", ane);
}
catch(ArgumentOutOfRangeException aore)
{
throw new ArgumentOutOfRangeException("Array Index must be zero or greater.", aore);
}
catch(ArgumentException ae)
{
throw new ArgumentException("Not enough room in array to copy elements starting at index given.", ae);
}
}
En termes du nouveau code ajouté que pourrait être le buggy, c'est encore pire. Et nous n'avons pas d'acquérir une chose de l'intérieur des exceptions. Si nous passons à une valeur nulle de la matrice de cette méthode et de recevoir une ArgumentNullException
, nous n'allons pas vous apprendre quoi que ce soit par l'examen de l'exception interne et de l'apprentissage qu'un appel à l' _innerList.CopyTo
a été adoptée null tableau et jeta un ArgumentNullException
.
Ici, nous pouvons faire tout ce que nous voulons, avec:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentException ae)
{
throw ae;
}
}
Chacun des exceptions que nous nous attendons à avoir à jeter si l'utilisateur appelle avec des arguments incorrects, sera bien jetés par que de re-jeter. Si il y a un bug dans la logique utilisée ici, c'est dans un de deux lignes - soit que nous avions tort de décider ce fut un cas où cette approche fonctionne, ou nous avons eu tort en ayant ArgumentException
comme le type d'exception cherché. C'est les deux seuls bugs que le bloc catch pouvez éventuellement avoir.
Maintenant. Je suis d'accord que la plupart du temps vous voulez une plaine throw;
ou vous voulez construire votre propre exception à plus directement en adéquation avec le problème du point de vue de la méthode en question. Il y a des cas comme ci-dessus où re-lancer comme cela fait plus de sens, et il y a beaucoup d'autres cas. E. g. pour prendre un tout autre exemple, si un ATOME lecteur de fichiers mis en œuvre avec un FileStream
et XmlTextReader
reçoit une erreur de fichier ou XML non valide, alors il va peut-être vouloir jeter exactement la même exception qu'il a reçu de ces classes, mais il devrait ressembler à l'appelant qu'il est AtomFileReader
qui est en train de jeter un FileNotFoundException
ou XmlException
, de sorte qu'ils pourraient être des candidats de de même re-lancement.
Edit:
Nous pouvons également combiner les deux:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentException ae)
{
throw ae;
}
catch(Exception ex)
{
//we weren't expecting this, there must be a bug in our code that put
//us into an invalid state, and subsequently let this exception happen.
LogException(ex);
throw;
}
}