Pourquoi un type jeté ou attrapé doit-il dériver de System.Exception

Donc, par simple curiosité, je voulais voir ce qui était spécial dans la classe d’exception qui lui permettait d’être utilisée avec le mot clé Throw alors qu’une classe standard ne l’était pas.

Tout ce que j’ai trouvé, c’est que la classe Exception a implémenté ce qui suit

 public class Exception : System.Object, System.Runtime.Serialization.ISerializable, System.Runtime.InteropServices._Exception { } 

J’ai donc essayé d’implémenter ces mêmes interfaces et de lancer ma propre exception personnalisée qui ne dérive pas de System.Exception en vain. J’ai simplement été informé que

Le type capturé ou jeté doit être dérivé de System.Exception

Y a-t-il une raison spécifique à cela? Je suppose qu’il y a peu de choix dans les langues gérées qui semblent être arbitraires.

Je pense que votre prémisse est erronée. Il est possible qu’un object renvoyé ne soit pas dérivé de System.Exception . Vous ne pouvez simplement pas le jeter en C # ou examiner l’object dans une clause catch. À partir de la section 8.10 de la spécification C # (v4.0):

Certains langages de programmation peuvent prendre en charge des exceptions non représentables en tant qu’object dérivé de System.Exception, bien que ces exceptions ne puissent jamais être générées par du code C #. Une clause de capture générale peut être utilisée pour intercepter de telles exceptions. Ainsi, une clause catch générale est sémantiquement différente de celle qui spécifie le type System.Exception, en ce sens que la première peut également intercepter des exceptions provenant d’autres langues.

Un exemple de prise générale:

 try { } catch (Exception) { } // 'specific' catch catch { } // 'general' catch 

Ceci est particulièrement important lorsque vous appelez du code non managé.

Certains types semblent toujours bénéficier d’un traitement spécial dans toutes les langues. Principalement parce qu’ils sont si fondamentaux pour le système. System.Exception , System.ValueType , System.Delegate sont tous des types spéciaux en C # étroitement liés aux mots-clés de langage et au CLR. Il n’est donc pas surprenant que vous ne puissiez pas implémenter des classes reprenant leurs rôles.

Directives de conception pour les exceptions

Les exceptions constituent le mécanisme standard pour signaler les erreurs. Les applications et les bibliothèques ne doivent pas utiliser les codes de retour pour communiquer les erreurs. L’utilisation d’exceptions ajoute à une conception de structure cohérente et permet aux membres, tels que les constructeurs, de signaler les erreurs qui ne peuvent pas avoir un type de retour.

throw (référence C #)

L’exception levée est un object dont la classe est dérivée de System.Exception, comme illustré dans l’exemple suivant.

 class MyException : System.Exception {} // ... throw new MyException(); 

Vue d’ensemble des exceptions

Dans le .NET Framework, une exception est un object qui hérite de la classe d’exception

Donc, votre exception doit dériver de System.Exception , mais c’est à vous de System.Exception comment vous l’organisez.

C’est un choix arbitraire des concepteurs du CLS. Vraisemblablement, ils ont fait ce choix pour des raisons de cohérence. C # suit le CLS; l’exigence est imposée par le compilateur pour cette raison et non pour une raison technique liée à la mise en œuvre du type d’exception.

La CLI peut réellement lancer n’importe quel object. Voir http://jilc.sourceforge.net/ecma_p3_cil.shtml#_Toc524462405 .

Le langage utilise System.Exception comme base pour toutes les exceptions. Cela signifie essentiellement que toute exception jetable ou capturable ne doit pas être erronée si vous faites (Exception)myExc . Cela est probablement dû au fait que la définition de la classe System.Exception est utilisée de sorte que toutes les exceptions adhèrent à la même interface. En raison de la cohérence de l’interface, les exceptions arrivent avec une trace de stack et un message significatif (par exemple), ce qui est très précieux pour la journalisation.

L’une des raisons pour lesquelles chaque exception doit avoir une classe de base universelle est que vous pouvez intercepter chaque type d’exception dans un seul bloc catch.

Si j’ai ceci:

 try { ... } catch(Exception ex) { // Handle somehow } 

Cela va attraper TOUTES les exceptions et me permettre d’afficher ce que c’est (en utilisant ex.Message ).

Si vous pouviez lancer quelque chose , alors comment auriez-vous une prise qui pourrait tout attraper tout en vous donnant access à l’object lancé?

Vous pourriez avoir ceci, qui attrapera absolument tout:

 try { ... } catch { // Handle somehow } 

Mais vous avez “perdu” la chose qui a été jetée.