90 votes

Pourquoi C # vous permet-il de "jeter à zéro"?

Quelqu'un a demandé lors de l'écriture d'un code de gestion des exceptions particulièrement complexe, ne devez-vous pas vous assurer que votre objet exception n'est pas nul? Et j'ai dit, bien sûr que non, mais j'ai ensuite décidé de l'essayer. Apparemment, vous pouvez lancer null, mais cela reste une exception quelque part.

Pourquoi est-ce permis?

 throw null;
 

Dans cet extrait, heureusement, «ex» n'est pas nul, mais est-ce possible?

 try
{
  throw null;
}
catch (Exception ex)
{
  //can ex ever be null?

  //thankfully, it isn't null, but is
  //ex is System.NullReferenceException
}
 

105voto

Mehrdad Afshari Points 204872

Parce que la spécification du langage s'attend à une expression de type System.Exception (donc, null est valable dans ce contexte) et de ne pas restreindre cette expression non-null. En général, il n'y a aucune manière qu'il pourrait détecter si la valeur de cette expression est - null ou pas. Il aurait à résoudre le problème de l'arrêt. Le moteur d'exécution à traiter avec de l' null de cas de toute façon. Voir:

Exception ex = null;
if (conditionThatDependsOnSomeInput) 
    ex = new Exception();
throw ex; 

Ils pourraient, bien sûr, faire le cas spécifique de jeter l' null littérale invalide, mais qui ne serait pas d'une grande aide, alors pourquoi gaspiller de la spécification de l'espace et de réduire la cohérence pour peu d'avantages?

Disclaimer (avant que je sois frappé par Eric Lippert): C'est mon propre spéculation sur le raisonnement derrière cette décision de conception. Bien sûr, je n'ai pas été dans la conception de réunion ;)


La réponse à votre deuxième question, à savoir si une expression variable capturé dans une clause catch peut jamais être nulle: Alors que le C# spécification est muette quant à savoir si d'autres langues peuvent causer null exception à être propagées, il n'définir la façon dont les exceptions sont propagées:

Les clauses catch, le cas échéant, sont examinées dans l'ordre d'apparition à trouver un gestionnaire pour l'exception. La première clause catch qui spécifie le type d'exception ou d'un type de base du type d'exception est considéré comme une correspondance. Un général de la clause catch est considéré comme un match pour n'importe quel type d'exception. [...]

Pour null, l'audacieuse affirmation est fausse. Ainsi, tout en se basant uniquement sur ce que le C# spec dit, on ne peut pas dire que le sous-jacent d'exécution ne jamais jeter nulle, on peut être sûr que, même si c'est le cas, elle va être traitées par le générique de l' catch {} de la clause.

Pour C# implémentations sur la CLI, nous pouvons nous référer à l'ECMA 335 spécification. Ce document définit toutes les exceptions que la CLI jette à l'interne (aucun n' null), et mentionne que définis par l'utilisateur exception des objets sont lancés par l' throw enseignement. La description pour que l'instruction est pratiquement identique à C# throw déclaration (sauf qu'il n'a pas restreindre le type de l'objet d' System.Exception):

Description:

L' throw instruction lève l'exception de l'objet (type O) sur la pile et vide la pile. Pour les détails du mécanisme d'exception, consultez la Partition de I.
[Remarque: lors de la CLI permet à n'importe quel objet à être jetés, le CEMAT a décrit une exception spécifique de la classe qui sera utilisée pour l'interopérabilité de langue. la note de fin]

Exceptions:

System.NullReferenceException est levée si obj est null.

Exactitude:

Corriger CIL s'assure que l'objet est toujours soit en null ou une référence d'objet (c'est à dire, de type O).

Je crois que ce sont suffisantes pour conclure pris exceptions ne sont jamais null.

31voto

Anon. Points 26829

Apparemment, vous pouvez lancer null, mais cela reste une exception quelque part.

Si vous tentez de lancer un objet null obtenez une exception de référence nulle (totalement indépendante).

Demander pourquoi vous êtes autorisé à jeter null revient à demander pourquoi vous êtes autorisé à le faire:

 object o = null;
o.ToString();
 

7voto

Brian Kennedy Points 637

Il peut ne pas être possible de jeter null en C# parce que le jet va le détecter et de le transformer en une NullReferenceException, il EST possible de recevoir nul... il m'arrive de recevoir aujourd'hui, ce qui provoque mes captures (qui ne s'attendait pas 'ex' être null) faire l'expérience d'une référence nulle exception, qui se traduit alors dans mon application est en train de mourir (puisque c'était la dernière prise).

Ainsi, alors que nous ne pouvons pas jeter null en C#, l'autre monde peut jeter nulle, de sorte que votre ultrapériphériques catch(Exception ex) mieux vaut être prêt à le recevoir. Juste pour info.

5voto

Fitzchak Yitzchaki Points 4896

Tiré d' ici :

Si vous utilisez cette expression dans votre code C #, une exception NullReferenceException sera générée. Cela est dû au fait que l'instruction throw a besoin d'un objet de type Exception en tant que paramètre unique. Mais cet objet même est nul dans mon exemple.

2voto

Steve Cooper Points 6637

Je pense que peut-être vous ne pouvez pas - lorsque vous essayez de lancer null, il ne peut pas, alors il fait ce qu'il devrait en cas d'erreur, à savoir lancer une exception de référence null. Donc, vous ne lancez pas le null, vous échouez, ce qui entraîne un lancer.

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