Casting direct vs ‘en tant qu’opérateur?

Considérez le code suivant:

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

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

 ssortingng s = (ssortingng)o; // 1 

Lance InvalidCastException si o n’est pas une ssortingng . Sinon, assigne o à s , même si o est null .

 ssortingng s = o as ssortingng; // 2 

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

 ssortingng s = o.ToSsortingng(); // 3 

Provoque une exception NullReferenceException si o est null . Assigne tout o.ToSsortingng() que o.ToSsortingng() renvoie à s , quel que soit le type o .


Utilisez 1 pour la plupart des conversions – c’est simple et direct. J’ai tendance à ne jamais utiliser 2 car si quelque chose n’est pas le bon type, je m’attends généralement à une exception. Je n’ai vu qu’un besoin de ce type de fonctionnalité de retour-null 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 dissortingbution et n’est qu’une invocation de méthode. Utilisez-le lorsque vous avez besoin de la représentation sous forme de chaîne d’un object non-chaîne.

  1. Utilisez quand quelque chose devrait définitivement être l’autre chose.
  2. Utilisez quand quelque chose pourrait être l’autre chose.
  3. Utilisez-le lorsque vous ne vous souciez pas de ce que c’est mais vous voulez simplement utiliser la représentation de chaîne disponible.

Cela dépend vraiment si vous savez si o est une chaîne et ce que vous voulez en faire. Si votre commentaire signifie que o est vraiment une chaîne, je préférerais la (ssortingng)o – il est peu probable qu’elle échoue.

Le plus grand avantage de l’utilisation du cast droit est que, en cas d’échec, vous obtenez une InvalidCastException , ce qui vous indique à peu près ce qui ne va pas.

Avec l’opérateur as , si o n’est pas une chaîne, s est défini sur null , ce qui est pratique si vous n’êtes pas sûr et que vous souhaitez tester s :

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

Cependant, si vous n’effectuez pas ce test, vous utiliserez s plus tard et une exception NullReferenceException sera lancée. Celles-ci ont tendance à être plus fréquentes et beaucoup plus difficiles à repérer une fois qu’elles se trouvent dans la nature, car presque toutes les lignes déréférencent une variable et peuvent en lancer une. D’un autre côté, si vous essayez de convertir en un type de valeur (n’importe quelle primitive, ou des structures telles que DateTime ), vous devez utiliser le lancer droit – le ne fonctionnera pas.

Dans le cas particulier de la conversion en chaîne de caractères, chaque object a un ToSsortingng , donc votre troisième méthode peut être correcte si o n’est pas nul et que vous pensez que la méthode ToSsortingng peut faire ce que vous voulez.

Si vous savez déjà à quel type vous pouvez lancer, utilisez une dissortingbution de style C:

 var o = (ssortingng) iKnowThisIsASsortingng; 

Notez que vous ne pouvez effectuer une coercition de type explicite qu’avec une dissortingbution de style C.

Si vous ne savez pas si c’est le type souhaité et que vous l’utiliserez s’il l’est, utilisez comme mot clé:

 var s = o as ssortingng; if (s != null) return s.Replace("_","-"); //or for early return: if (s==null) return; 

Notez que as n’appellera aucun opérateur de conversion de type. Il sera uniquement non nul si l’object n’est pas nul et natif du type spécifié.

Utilisez ToSsortingng () pour obtenir une représentation sous forme de chaîne lisible par l’homme de tout object, même s’il ne peut pas être converti en chaîne.

Le mot clé as est bien 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 saisie plutôt que de la lancer depuis un object comme vous le feriez avec une dissortingbution directe:

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

Ce n’est pas une chose énorme, mais cela permet d’économiser des lignes de code et des affectations de variables, en plus c’est plus lisible

‘as’ est basé sur ‘is’, qui est un mot clé qui vérifie à l’exécution si l’object est compatible polimorphycally (essentiellement si une dissortingbution peut être faite) et renvoie null si la vérification échoue.

Ces deux sont équivalents:

Utiliser ‘as’:

 ssortingng s = o as ssortingng; 

Utiliser ‘is’:

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

Au contraire, la dissortingbution de style c est faite également à l’exécution, mais lance une exception si la dissortingbution ne peut pas être faite.

Juste pour append un fait important:

Le mot clé ‘as’ ne fonctionne qu’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.

2 est utile pour la casting à un type dérivé.

Supposons que un est un animal:

 b = a as Badger; c = a as Cow; if (b != null) b.EatSnails(); else if (c != null) c.EatGrass(); 

va recevoir un aliment avec un minimum de lancers.

“(ssortingng) o” entraînera une InvalidCastException car il n’y a pas de dissortingbution directe.

“o as ssortingng” aura pour résultat que s est une référence nulle, plutôt qu’une exception étant lancée.

“o.ToSsortingng ()” n’est pas une dissortingbution 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 à laquelle elle est appelée et renvoie une chaîne.

N’oubliez pas que pour convertir en chaîne, il existe également Convert.ToSsortingng (someType instanceOfThatType) où someType fait partie d’un ensemble de types, essentiellement les types de base des frameworks.

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

(Cette page contient parfois des erreurs de “référent illégal”, alors rafraîchissez-la si c’est le cas)

La conclusion est que l’opérateur “as” est normalement plus rapide qu’un cast. Parfois, plusieurs fois plus vite, parfois à peine plus vite.

Je pense que la chose “comme” est aussi plus lisible.

Donc, comme il est à la fois plus rapide et “plus sûr” (ne pas envoyer d’exception), et peut-être plus facile à lire, je recommande d’utiliser “comme” tout le temps.

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

 (ssortingng)o.ToLower(); // won't comstack 

vous ne pouvez écrire que:

 ((ssortingng)o).ToLower(); 

mais vous pourriez écrire à la place:

 (o as ssortingng).ToLower(); 

L’option est plus lisible (au moins à mon avis).

 ssortingng s = o as ssortingng; // 2 

Est préféré, car il évite la pénalité de performance de double casting.

Il semble que les deux soient conceptuellement différents.

Coulée directe

Les types ne doivent pas nécessairement être ssortingctement liés. Il existe dans tous les types de saveurs.

  • Transtypage implicite / explicite personnalisé: généralement, un nouvel object est créé.
  • Type de valeur Implicite: Copier sans perdre d’informations.
  • Type de valeur Explicite: La copie et les informations peuvent être perdues.
  • Relation IS-A: Modifier le type de référence, sinon génère une exception.
  • Même type: “Casting est redondant”.

On a l’impression que l’object va être converti en autre chose.

Opérateur AS

Les types ont une relation directe. Un péché:

  • Types de référence: relation IS-A Les objects sont toujours les mêmes, juste les changements de référence.
  • Types de valeur: Copier les types boxing et nullable.

On a l’impression que vous allez manipuler l’object d’une manière différente.

Échantillons et IL

  class TypeA { public int value; } class TypeB { public int number; public static explicit operator TypeB(TypeA v) { return new TypeB() { number = v.value }; } } class TypeC : TypeB { } interface IFoo { } class TypeD : TypeA, IFoo { } void Run() { TypeA customTypeA = new TypeD() { value = 10 }; long longValue = long.MaxValue; int intValue = int.MaxValue; // Casting TypeB typeB = (TypeB)customTypeA; // custom explicit casting -- IL: call class ConsoleApp1.Program/TypeB ConsoleApp1.Program/TypeB::op_Explicit(class ConsoleApp1.Program/TypeA) IFoo foo = (IFoo)customTypeA; // is-a reference -- IL: castclass ConsoleApp1.Program/IFoo int loseValue = (int)longValue; // explicit -- IL: conv.i4 long dontLose = intValue; // implict -- IL: conv.i8 // AS int? wraps = intValue as int?; // nullable wrapper -- IL: call instance void valuetype [System.Runtime]System.Nullable`1::.ctor(!0) object o1 = intValue as object; // box -- IL: box [System.Runtime]System.Int32 TypeD d1 = customTypeA as TypeD; // reference conversion -- IL: isinst ConsoleApp1.Program/TypeD IFoo f1 = customTypeA as IFoo; // reference conversion -- IL: isinst ConsoleApp1.Program/IFoo //TypeC d = customTypeA as TypeC; // wouldn't comstack } 

En essayant d’obtenir la représentation sous forme de chaîne de tout ce qui pourrait être nul, je préfère la ligne de code ci-dessous. C’est compact, il appelle ToSsortingng () et gère correctement les valeurs NULL. Si o est nul, s contiendra Ssortingng.Empty.

 Ssortingng s = Ssortingng.Concat(o); 

Comme personne ne l’a mentionné, le plus proche d’instanceOf pour Java par mot clé est le suivant:

 obj.GetType().IsInstanceOfType(otherObj) 

Utilisez la ssortingng s = (ssortingng) o; diffusion directe ssortingng s = (ssortingng) o; si dans le contexte logique de votre application, la ssortingng est le seul type valide. Avec cette approche, vous obtiendrez InvalidCastException et implémentez le principe de Fail-Fast . Votre logique ne sera plus transmise le type invalide ou obtiendra une exception NullReferenceException si elle est utilisée as opérateur.

Si la logique attend plusieurs types différents, lancez la ssortingng s = o as ssortingng; et vérifiez-le sur null ou utilisez l’opérateur.

Une nouvelle fonctionnalité intéressante est apparue dans C # 7.0 pour simplifier la dissortingbution et la vérification est une correspondance de modèle :

 if(o is ssortingng s) { // Use ssortingng variable s } or switch (o) { case int i: // Use int variable i break; case ssortingng s: // Use ssortingng variable s break; } 

Les deux formes suivantes de conversion de type (conversion) sont sockets en charge dans C #:

|

(CV

• Convertir le type statique de v en c dans l’expression donnée

• Uniquement possible si le type dynamic de v est c ou un sous-type de c

• Sinon, une InvalidCastException est levée

|

v comme C

• Variante non fatale de (c) v

• Ainsi, convertissez le type statique de v en c dans l’expression donnée

• Retourne null si le type dynamic de v n’est pas c, ou un sous-type de c