Question Casting direct vs opérateur 'as'?


Considérez le code suivant:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

Quelle est la différence entre les trois types de casting (d'accord, le 3ème n'est pas un casting, mais vous obtenez l'intention). Lequel devrait être préféré?


578
2017-09-25 10:09


origine


Réponses:


string s = (string)o; // 1

Jette InvalidCastException si o n'est pas un string. Sinon, assigne o à s, même si o est null.

string s = o as string; // 2

Assigne null à s si o n'est pas un string ou si o est null. Pour cette raison, vous ne pouvez pas l'utiliser avec des types de valeur (l'opérateur ne peut jamais retourner null dans ce cas). Sinon, assigne o à s.

string s = o.ToString(); // 3

Provoque une NullReferenceException si o est null. Assigne tout o.ToString() retourne à s, peu importe le type o est.


Utilisez 1 pour la plupart des conversions - c'est simple et direct. J'ai tendance à n'utiliser presque jamais 2 puisque si quelque chose n'est pas le bon type, je m'attends généralement à une exception. J'ai seulement vu un besoin pour ce type de fonctionnalité de retour nul avec des bibliothèques mal conçues qui utilisent des codes d'erreur (par exemple, return null = error, au lieu d'utiliser des exceptions).

3 n'est pas une distribution et est juste une invocation de méthode. Utilisez-le lorsque vous avez besoin de la représentation sous forme de chaîne d'un objet non-chaîne.


694
2017-09-25 10:16



  1. Utiliser quand quelque chose devrait absolument être l'autre chose.
  2. Utiliser quand quelque chose pourrait être L'autre chose.
  3. Utilisez quand vous ne vous souciez pas de quoi c'est mais vous voulez juste utiliser le représentation de chaîne disponible.

285
2017-09-25 10:31



Cela dépend vraiment si vous savez si o est une chaîne et ce que vous voulez faire avec. Si votre commentaire signifie que o vraiment est une chaîne, je préfère la ligne droite (string)o cast - il est peu probable d'échouer.

Le plus grand avantage de l'utilisation de la distribution droite est que quand il échoue, vous obtenez un InvalidCastException, qui vous dit à peu près ce qui s'est mal passé.

Avec le as opérateur, si o n'est pas une chaîne, s est réglé sur null, ce qui est pratique si vous n'êtes pas sûr et que vous voulez tester s:

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

Cependant, si vous n'effectuez pas ce test, vous utiliserez s plus tard et avoir un NullReferenceException jeté. Ceux-ci ont tendance à être plus commun et un lot plus difficile de traquer une fois qu'ils se produisent dans la nature, car presque chaque ligne déréférence une variable et peut en jeter un. D'un autre côté, si vous essayez de convertir un type de valeur (n'importe quelle primitive, ou des structures telles que DateTime), vous devez utiliser le casting droit - le as ne fonctionnera pas.

Dans le cas particulier de la conversion en chaîne, chaque objet a un ToString, donc votre troisième méthode peut-être bien si o n'est pas nul et vous pensez que le ToString méthode pourrait faire ce que vous voulez.


26
2017-09-25 10:16



Si vous connaissez déjà le type de diffusion, utilisez une distribution de style C:

var o = (string) iKnowThisIsAString; 

Notez que seul un casting de style C peut effectuer une contrainte de type explicite.

Si vous ne savez pas si c'est le type désiré et que vous allez l'utiliser si c'est le cas, utilisez comme mot-clé:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

Notez que comme n'appellera aucun opérateur de conversion de type. Il ne sera pas nul si l'objet n'est pas nul et natif du type spécifié.

Utilisez ToString () pour obtenir une représentation de chaîne de caractères lisible par un humain, même si elle ne peut pas être convertie en chaîne.


8
2017-09-25 10:41



Le mot-clé as est bon dans asp.net lorsque vous utilisez la méthode FindControl.

Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
     ...
}

Cela signifie que vous pouvez opérer sur la variable typée plutôt que de la lancer ensuite object comme avec une distribution directe:

object linkObj = this.FindControl("linkid");
if (link != null)
{
     Hyperlink link = (Hyperlink)linkObj;
}

Ce n'est pas énorme, mais cela permet d'économiser des lignes de code et d'assigner des variables, en plus c'est plus lisible


7
2017-09-25 11:17



'as' est basé sur 'is', qui est un mot-clé qui vérifie à l'exécution si l'objet est compatible polimorphycally (fondamentalement si un cast peut être fait) et renvoie null si la vérification échoue.

Ces deux sont équivalents:

En utilisant 'comme':

string s = o as string;

En utilisant 'est':

if(o is string) 
    s = o;
else
    s = null;

Au contraire, la distribution de style c est également effectuée au moment de l'exécution, mais elle déclenche une exception si la conversion n'est pas possible.

Juste pour ajouter un fait important:

Le mot clé 'as' fonctionne uniquement avec les types de référence. Tu ne peux pas faire:

// I swear i is an int
int number = i as int;

Dans ces cas, vous devez utiliser le casting.


6
2017-09-25 10:15



2 est utile pour la conversion en un type dérivé.

Supposer une est un animal:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

aura une nourri avec un minimum de moulages.


5
2017-09-25 10:31



"(string) o" entraînera une InvalidCastException car il n'y a pas de conversion directe.

"o comme chaîne" aura pour résultat que s est une référence nulle, plutôt qu'une exception étant levée.

"o.ToString ()" n'est pas une distribution en soi, c'est une méthode implémentée par object, et donc d'une manière ou d'une autre, par chaque classe de .net qui "fait quelque chose" avec l'instance de la classe est appelée et renvoie une chaîne.

N'oubliez pas que pour la conversion en chaîne, il y a aussi Convert.ToString (someType instanceOfThatType) où someType est l'un d'un ensemble de types, essentiellement les types de base des frameworks.


4
2017-09-25 10:17



Selon les expériences effectuées sur cette page: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(cette page fait parfois apparaître des erreurs de "référent illégal", donc rafraîchissez-vous si c'est le cas)

Conclusion, l'opérateur "as" est normalement plus rapide qu'un cast. Parfois par plusieurs fois plus vite, parfois juste à peine plus vite.

Je peronsonally chose "comme" est également plus lisible.

Donc, comme il est à la fois plus rapide et "plus sûr" (pas d'exception de lancement), et peut-être plus facile à lire, je recommande d'utiliser "comme" tout le temps.


3
2017-08-15 18:36



Toutes les réponses données sont bonnes, si je peux ajouter quelque chose: Pour utiliser directement les méthodes et propriétés de la chaîne (par exemple ToLower), vous ne pouvez pas écrire:

(string)o.ToLower(); // won't compile

vous pouvez seulement écrire:

((string)o).ToLower();

mais vous pourriez écrire à la place:

(o as string).ToLower();

le as option est plus lisible (au moins à mon avis).


3
2018-04-03 14:28