2009-06-28 26 views
1

En Delphi, s'il y avait une exception lors de la construction d'un objet: toute mémoire allouée serait libérée et une exception serait levée. Par exemple, ce qui suit est garanti soit retourner un objet valide Camera, ou lancer une exception:CLR: Si un constructeur échoue, va-t-il toujours lancer une exception?

Camera c = new Camera(); 

Vous jamais devait vérifier la variable résultante pour null:

Camera c = new Camera(); 
if (c == null) 
    throw new Exception("Error constructing Camera") //waste of time 

Est-ce la même chose dans le CLR?

Y a-t-il d'autres constuites syntatiques dans lesquelles une valeur de retour est garantie, soit valide, soit une exception?

  • Création de structures (par exemple Rectangle)?
  • Obtenir un membre d'un recensement?
  • le résultat de Object.ToString()?
  • opérations mathématiques?

Dans le cas d'effectuer les mathématiques:

Int32 aspect = 1650.0/1080.0; 
if (aspect == null) 
    throw new Exception("Division of two numbers returned null") 

Répondre

3

Un constructeur dans .Net est garanti de renvoyer une instance non nulle du type de l'objet. Si l'instance est valide dépend de la sémantique individuelle du type.

Les exceptions levées dans un constructeur ne seront pas avalées arbitrairement par le CLR (bien que le code utilisateur puisse les avaler).Le CLR propagera une exception comme les exceptions lancées dans toute autre méthode et les objets seront finalement correctement récupérés.

En ce qui concerne les autres cas, vous avez mentionné

  • Création structures: par définition, ne peut jamais être nulle. Les exceptions lancées dans le constructeur propagera normalement
  • Obtenir un membre d'une énumération: énumérations sont strutures/types de valeurs sous le capot et aussi ne jamais nulle
  • le résultat de Object.ToString(): Cela peut (et malheureusement) sera nul. String est un type de référence et il est parfaitement légal de renvoyer null à partir d'un override ToString (ne le faites pas).
  • Opérations mathématiques: Cela dépend fortement à la fois du paramètre de dépassement de capacité de votre projet et du type particulier utilisé (intégrale ou virgule flottante).

La question mathématique mérite presque une réponse par elle-même. D'une part, le résultat d'une opération mathématique sur les types primitifs ne sera jamais nul. Mais il peut toujours être invalide. Par exemple, le code suivant ne pas jeter, mais si le résultat est valable dépend fortement de votre scénario spécifique

float f1 = 1.0; 
float f2 = f1/0; 

A ce stade, f2 est une valeur flottante très spécifique qui ne représente pas un nombre réel. Est-ce valide? Cela dépend de votre cas d'utilisation.

1

Oui. Je voudrais le mettre de cette façon (comme échouer pourrait signifier échec logique aussi): Si un constructeur ne lève pas une exception, la valeur de retour est garanti pour être non null de sorte que vous n'avez jamais à effectuer une telle un chèque.

Création de structures (par exemple Rectangle): Un struct ne peut pas être null du tout (Nullable types sont considérés comme des types complètement différents, à savoir typeof(int?) != typeof(int)). Appeler un constructeur pour une structure échouerait en lançant une exception ou retourner une instance. Obtention d'un membre d'une énumération: un enum est juste un ensemble de constantes. Il n'y a rien comme "obtenir un membre à l'exécution." Il est substitué au moment de la compilation.

Le résultat de Object.ToString(): Comme toute méthode, il peut renvoyer une valeur valide pour le type string qui comprend null et pourrait également lancer une exception (dans ce cas, il ne retourne pas de valeur du tout). Opérations mathématiques: Toutes les expressions renverront une valeur ou déclencheront une exception. La valeur de retour peut être n'importe quelle valeur valide pour ce type (par exemple Int32 ne peut jamais être null).