C # “comme” cast vs casting classique

Duplication possible:
Casting vs en utilisant le mot clé ‘as’ dans le CLR

J’ai récemment appris une autre façon de lancer. Plutôt que d’utiliser

SomeClass someObject = (SomeClass) obj; 

on peut utiliser cette syntaxe:

 SomeClass someObject = obj as SomeClass; 

qui semble retourner null si obj n’est pas une classe SomeClass, plutôt que de lancer une exception de conversion de classe.

Je vois que cela peut mener à une exception NullReferenceException si la dissortingbution échoue et que j’essaie d’accéder à la variable someObject. Je me demande donc quelle est la raison d’être de cette méthode? Pourquoi devrait-on utiliser cette méthode de casting plutôt que celle (ancienne) – il semble que le problème de la dissortingbution échouée ne soit que plus profond dans le code.

Avec la méthode “classique”, si la conversion échoue, une exception est levée. Avec la méthode as, il en résulte null, ce qui peut être vérifié et éviter qu’une exception soit lancée.

En outre, vous ne pouvez utiliser “as” qu’avec des types de référence, donc si vous transformez en un type de valeur, vous devez toujours utiliser la méthode “classique”.

Remarque:

La méthode as ne peut être utilisée que pour les types pouvant recevoir une valeur null . Cela ne signifie que les types de référence, mais lorsque .NET 2.0 est sorti, il a introduit le concept d’un type de valeur nullable. Comme ces types peuvent recevoir une valeur null , ils sont valables pour être utilisés avec l’opérateur as .

La comparaison nulle est BEAUCOUP plus rapide que lancer et attraper une exception. Les exceptions sont significatives – la trace de la stack doit être assemblée, etc.

Les exceptions doivent représenter un état inattendu, qui souvent ne représente pas la situation (qui fonctionne mieux).

Dans certains cas, il est facile de traiter un null plutôt qu’une exception. En particulier, l’opérateur de coalescence est pratique:

 SomeClass someObject = (obj as SomeClass) ?? new SomeClass(); 

Il simplifie également le code là où vous vous trouvez (sans utiliser de polymorphism, et) le twigment en fonction du type d’object:

 ClassA a; ClassB b; if ((a = obj as ClassA) != null) { // use a } else if ((b = obj as ClassB) != null) { // use b } 

Comme spécifié sur la page MSDN , l’opérateur as est équivalent à:

 expression is type ? (type)expression : (type)null 

ce qui évite complètement l’exception en faveur d’un test de type plus rapide, mais limite également son utilisation aux types qui supportent null (types de référence et Nullable ).

L’opérateur as est utile dans quelques circonstances.

  1. Lorsque vous avez seulement besoin de connaître un object est d’un type spécifique, mais vous n’avez pas besoin d’agir spécifiquement sur les membres de ce type
  2. Lorsque vous souhaitez éviter les exceptions et plutôt traiter explicitement null
  3. Vous voulez savoir s’il existe une conversion CLR entre les objects et pas seulement une conversion définie par l’utilisateur.

Le 3ème point est subtil mais important. Il n’y a pas de mappage 1-1 entre les castes qui réussiront avec l’opérateur de casting et ceux qui réussiront avec l’opérateur as . L’opérateur as est ssortingctement limité aux conversions CLR et ne tiendra pas compte des conversions définies par l’utilisateur (l’opérateur de la dissortingbution sera).

Plus précisément, l’opérateur as ne permet que les éléments suivants (section 7.9.11 de la spécification C # lang)

  • Une conversion identité (§6.1.1), référence implicite (§6.1.6), boxe (§6.1.7), référence explicite (§6.2.4) ou unboxing (§6.2.5) existe à partir du type de E à T.
  • Le type de E ou T est un type ouvert.
  • E est le littéral nul.

Le mot-clé as est utile lorsque vous ne connaissez pas vraiment le type de la variable. Si vous avez une seule fonction qui suivra des chemins de code différents selon le type du paramètre, vous avez deux choix:

D’abord, en utilisant une dissortingbution normale:

 if(myObj is ssortingng) { ssortingng value = (ssortingng)myObj; ... do something } else if(myObj is MyClass) { MyClass = (MyClass)myObj; } 

Cela nécessite que vous vérifiiez le type de l’object utilisé afin de ne pas essayer de le convertir en quelque chose qui échouera. Ceci est également légèrement redondant, car la vérification is -type est effectuée à nouveau dans la dissortingbution (afin de pouvoir lancer l’exception si nécessaire).

L’alternative est d’utiliser as .

 ssortingng mySsortingng = myObj as ssortingng; MyClass myClass = myObj as MyClass; if(mySsortingng != null) { } else if(myClass != null) { } 

Cela rend le code un peu plus court et élimine également la vérification de type redondante.

utiliser as retournera null si ce n’est pas une dissortingbution valide qui vous permet de faire autre chose que d’envelopper la dissortingbution dans un try / catch. Je déteste le casting classique. J’utilise toujours comme casting si je ne suis pas sûr. De plus, les exceptions sont chères. Les vérifications nulles ne le sont pas.

Je pense que la meilleure «règle» serait de n’utiliser que le mot-clé «as» lorsque l’on s’attend à ce que votre sujet ne soit pas l’object vers lequel vous voulez lancer:

 var x = GiveMeSomething(); var subject = x as Ssortingng; if(subject != null) { // do what you want with a ssortingng } else { // do what you want with NOT a ssortingng } 

Cependant, lorsque votre sujet DEVRAIT être du type que vous utilisez, utilisez un «casting classique», comme vous l’appelez. Parce que si ce n’est pas le type que vous attendez, vous obtiendrez une exception qui correspond à la situation exceptionnelle.

Il n’y a rien de profond qui se passe ici. Fondamentalement, il est pratique de tester quelque chose pour voir s’il est d’un certain type (c’est-à-dire utiliser ‘as’). Vous voudriez vérifier le résultat de l’appel “as” pour voir si le résultat est nul.

Lorsque vous vous attendez à ce que la dissortingbution fonctionne et que vous souhaitiez que l’exception soit déclenchée, utilisez la méthode “classique”.

Vous utilisez l’instruction “as” pour éviter la possibilité d’une exception, par exemple, vous pouvez gérer l’échec de la dissortingbution via la logique. N’utilisez le cast que lorsque vous êtes certain que l’object est du type souhaité. J’utilise presque toujours le “as” et vérifie la valeur null.

Je suppose que c’est utile si le résultat de la dissortingbution est passé à une méthode qui, vous le savez, va gérer les références NULL sans lancer et ArgumentNullException ou similaire.

J’ai tendance à trouver très peu d’utilité pour, puisque:

 obj as T 

Est plus lent que:

 if (obj is T) ...(T)obj... 

L’utilisation de as est vraiment un scénario de bord pour moi, donc je ne peux penser à aucune règle générale pour savoir quand je l’utiliserais juste pour lancer et gérer l’exception de casting (plus informative) plus haut dans la stack.