Question

Doublon possible :
Casting ou utilisation du mot-clé « as » dans le CLR

Quelle est réellement la différence entre ces deux castings ?

SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;

Normalement, ils devraient tous deux être des conversions explicites vers le type spécifié ?

Était-ce utile?

La solution

Le premier lèvera une exception si le type source ne peut pas être converti en type cible.Dans ce dernier cas, sc2 sera une référence nulle, mais sans exception.

[Modifier]

Ma réponse originale est certainement la différence la plus prononcée, mais comme Eric Lippert fait remarquer, ce n'est pas le seul.D'autres différences incluent :

  • Vous ne pouvez pas utiliser l'opérateur "as" pour convertir en un type qui n'accepte pas "null" comme valeur.
  • Vous ne pouvez pas utiliser « comme » pour convertir des choses, comme des nombres vers une représentation différente (float vers int, par exemple).

Et enfin, en utilisant « comme » vs.l'opérateur de distribution, vous dites également "Je ne suis pas sûr que cela réussisse".

Autres conseils

Notez également que vous ne pouvez utiliser le mot-clé as qu'avec un type référence ou un type nullable.

c'est à dire:

double d = 5.34;
int i = d as int;

ne compilera pas

double d = 5.34;
int i = (int)d;

va compiler.

Le transtypage utilisant "as" est bien sûr beaucoup plus rapide lorsque le transtypage échoue, car il évite les dépenses liées à la levée d'une exception.

Mais cela ne va pas plus vite lorsque le casting est réussi.Le graphique à http://www.codeproject.com/KB/cs/csharpcasts.aspx est trompeur car il n’explique pas ce qu’il mesure.

L’essentiel est :

  • Si vous vous attendez à ce que le casting réussisse (c.-à-d.un échec serait exceptionnel), utiliser un plâtre.

  • Si vous ne savez pas si cela réussira, utilisez l'opérateur "as" et testez le résultat pour null.

Une différence entre les deux approches est que la première ((SomeClass)obj) peut provoquer un convertisseur de type être appelé.

Voici une bonne façon de me souvenir du processus que chacun d’eux suit et que j’utilise pour essayer de décider lequel est le mieux adapté à ma situation.

DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);

et le suivant devrait être facile à deviner ce qu'il fait

DateTime i = value as DateTime;

dans le premier cas, si la valeur ne peut pas être convertie, une exception est levée dans le second cas si la valeur ne peut pas être convertie, i est défini sur null.

Ainsi, dans le premier cas, un arrêt brutal est effectué si la distribution échoue. Dans le deuxième cas, un arrêt progressif est effectué et vous pourriez rencontrer une NullReferenceException plus tard.

Bien l'opérateur 'as' vous "aide" à enterrer votre problème bien plus bas car lorsqu'une instance incompatible lui est fournie, elle renverra null, vous la transmettrez peut-être à une méthode qui la transmettra à une autre et ainsi de suite et enfin vous obtiendrez une NullReferenceException qui rendra votre débogage plus difficile.

N'en abusez pas.L'opérateur de coulée directe est meilleur dans 99% des cas.

Pour développer Le commentaire de Rytmis, vous ne pouvez pas utiliser le comme mot-clé pour les structures (types de valeur), car elles n'ont pas de valeur nulle.

Tout cela s'applique aux types référence, les types valeur ne peuvent pas utiliser le as mot-clé car ils ne peuvent pas être nuls.

//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;


//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;

La syntaxe de conversion est plus rapide, mais seulement en cas de succès, l'échec est beaucoup plus lent.

La meilleure pratique consiste à utiliser as quand on ne connaît pas le type :

//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;

//use as to find the right type
if( ( sc = someObject as SomeClass ) != null ) 
{
    //do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null ) 
{
    //do something with soc
}

Cependant, si vous êtes absolument sûr que someObject est un exemple de SomeClass puis utilisez cast.

Dans .Net 2 ou supérieur, les génériques signifient que vous avez très rarement besoin d'avoir une instance non typée d'une classe de référence, cette dernière est donc moins souvent utilisée.

La conversion entre parenthèses lève une exception si la tentative de conversion échoue.Le cast "as" renvoie null si la tentative de cast échoue.

Ils lanceront différentes exceptions.
() :NullReferenceException
comme :InvalidCastException
Ce qui pourrait aider au débogage.

Le mot-clé "as" tente de convertir l'objet et si la conversion échoue, null est renvoyé silencieusement.L'opérateur de conversion () lèvera une exception immédiatement si la conversion échoue.

"Utilisez uniquement le mot-clé C# "as" lorsque vous vous attendez à ce que la conversion échoue dans un cas non exceptionnel.Si vous comptez sur un cast pour réussir et que vous n'êtes pas prêt à recevoir un objet qui échouerait, vous devez utiliser l'opérateur de cast () afin qu'une exception appropriée et utile soit levée."

Pour des exemples de code et une explication supplémentaire : http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

C'est comme la différence entre Parse et TryParse.Vous utilisez TryParse lorsque vous pensez qu'il risque d'échouer, mais lorsque vous avez la certitude qu'il n'échouera pas, vous utilisez Parse.

Pour ceux d'entre vous ayant une expérience VB.NET, (type) est le même que DirectCast et "as type" est le même que TryCast.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top