Double Possible:
Casting vs à l'aide de l' " comme mot-clé dans la CLRJ'ai récemment appris une autre façon de fonte. Plutôt que d'utiliser
SomeClass someObject = (SomeClass) obj;
on peut utiliser cette syntaxe:
SomeClass someObject = obj as SomeClass;
qui semble renvoyer la valeur null si obj n'est pas un SomeClass, plutôt que de lancer une classe fonte d'exception.
Je vois que cela peut conduire à une exception NullReferenceException si le casting a échoué et j'essaie d'accéder à la someObject variable. Alors je me demandais quelle est la justification de cette méthode? Pourquoi devrait-on utiliser ce moyen de la fonte plutôt que de la (vieille) il semble que déplacer le problème de l'échec d'une fonte "plus en profondeur" dans le code.
- Casting vs à l’aide de la ' comme ' mot-clé dans le CLR (5 réponses )
Réponses
Trop de publicités?Avec le "classique" de la méthode, si la conversion échoue, une exception est levée. Avec la méthode, il en résulte la valeur null, ce qui peut être vérifié, et d'éviter une exception levée.
Aussi, vous pouvez seulement utiliser "que" avec les types de référence, donc si vous êtes typecasting à un type de valeur, vous devez toujours utiliser le "classique" de la méthode.
Edit:
Depuis cette réponse est en train de devenir populaire, j'ai pensé que je voudrais corriger le paragraphe précédent (merci à ceux qui ont commenté et a souligné pour moi). L' as
méthode ne peut être utilisée pour les types qui peuvent être affectés à une null
de la valeur. Que l'utilisation de seulement les types de référence, mais quand .NET 2.0 est sorti, il introduit la notion de nullable type de valeur. Étant donné que ces types de peut être affecté à une null
de la valeur, ils sont valables pour une utilisation avec l' as
de l'opérateur.
La comparaison nulle est beaucoup plus rapide que la levée et l’interception des exceptions. Exceptions ont une surcharge significative - trace de la pile doit être assemblée etc.
Exceptions devraient représenter un état inattendu, qui souvent ne représente pas la situation (qui est à ce moment `` fonctionne mieux).
Dans certains cas, il est facile de traiter avec un null
qu'une exception. En particulier, la coalescence de l'opérateur est à portée de main:
SomeClass someObject = (obj as SomeClass) ?? new SomeClass();
Il simplifie également le code là où vous êtes (à ne pas utiliser le polymorphisme, et) de branchement en fonction du type d'un objet:
ClassA a;
ClassB b;
if ((a = obj as ClassA) != null)
{
// use a
}
else if ((b = obj as ClassB) != null)
{
// use b
}
Comme précisé sur la page MSDN, l' as
opérateur est équivalent à:
expression is type ? (type)expression : (type)null
ce qui évite l'exception totalement en faveur d'une plus vite type de test, mais aussi les limites de son utilisation à des types qui prennent en charge null
(types de référence et d' Nullable<T>
).
L' as
opérateur est utile dans plusieurs circonstances.
- Quand vous avez seulement besoin de savoir qu'un objet est d'un type spécifique, mais n'ont pas besoin spécifiquement de la loi sur les membres de ce type
- Si vous souhaitez éviter les exceptions et à la place explicitement traitent
null
- Vous voulez savoir si il y a un CLR conversion entre les objets et non pas seulement de certains défini par l'utilisateur de conversion.
Le 3ème point est subtile mais importante. Il n'y a pas un mappage 1-1 entre ce qui jette un va réussir avec l'opérateur de cast et ceux qui vont réussir avec l' as
de l'opérateur. L' as
opérateur est strictement limitée à la CLR conversions et ne considérera pas les conversions définies par l'utilisateur (l'opérateur de cast).
Plus précisément l' as
opérateur permet uniquement pour les suivants (à partir de la section 7.9.11 du C# lang spec)
- Une identité (§6.1.1), référence implicite (§6.1.6), la boxe (§6.1.7), référence explicite (§6.2.4), ou unboxing (§6.2.5) conversion existe à partir du type de E T.
- Le type de E ou T est un type ouvert.
- E est le littéral null.
L' as
mot-clé est utile lorsque vous avez réellement ne savez pas quel type de la variable peut être. Si vous avez une seule fonction qui va suivre différents chemins de code selon la catégorie de paramètre, alors vous avez deux choix:
Tout d'abord, à l'aide d'un normal en fonte:
if(myObj is string)
{
string value = (string)myObj;
... do something
}
else if(myObj is MyClass)
{
MyClass = (MyClass)myObj;
}
Cela exige que vous vérifiez le type de l'objet à l'aide d' is
, de sorte que vous n'essayez pas de le convertir en quelque chose qui va à l'échec. C'est aussi un peu redondant, comme l' is
-type de la vérification se fait à nouveau dans le casting (de sorte qu'il peut lancer une exception si nécessaire).
L'alternative est d'utiliser as
.
string myString = myObj as string;
MyClass myClass = myObj as MyClass;
if(myString != null)
{
}
else if(myClass != null)
{
}
Cela rend le code un peu plus courte et élimine également le redondante vérification de type.