web-dev-qa-db-fra.com

Quel est l'intérêt du mot clé "As" en C #

De la documentation:

L'opérateur as est comme un transtypage, sauf qu'il renvoie null en cas d'échec de conversion au lieu de déclencher une exception. Plus formellement, une expression de la forme:

   expression as type

est équivalent à:

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

sauf que l'expression n'est évaluée qu'une seule fois.

Alors, pourquoi ne choisiriez-vous pas de le faire dans un sens ou dans l'autre? Pourquoi avoir deux systèmes de casting?

56
astronought

Ce ne sont pas deux systèmes de casting. Les deux ont des actions similaires mais des significations très différentes. Un "comme" signifie "Je pense que cet objet pourrait être en fait de cet autre type; donnez-moi une valeur nulle s'il ne l'est pas." Un casting signifie l'une des deux choses suivantes:

  • Je sais avec certitude que cet objet est en fait de cet autre type. Faites-le, et si je me trompe, plantez le programme.

  • Je sais avec certitude que cet objet n'est pas de cet autre type, mais qu'il existe un moyen bien connu de convertir la valeur du type actuel en le type souhaité. (Par exemple, transtypage int en short.) Faites-le, et si la conversion ne fonctionne pas réellement, plantez le programme.

Voir mon article sur le sujet pour plus de détails.

http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

81
Eric Lippert

Parce que parfois, vous voulez que les choses échouent si vous ne pouvez pas lancer comme vous l'attendez, et d'autres fois, vous ne vous en souciez pas et vous voulez simplement jeter un objet donné s'il ne peut pas lancer.

Il s'agit essentiellement d'une version plus rapide d'une distribution régulière enveloppée dans un bloc try; mais As est beaucoup plus lisible et économise également la saisie.

12
Amber

Efficacité et performances

Une partie de l'exécution d'un casting est une vérification de type intégrée; donc le préfixe de la distribution réelle avec une vérification de type explicite est redondant (la vérification de type se produit deux fois). L'utilisation du mot clé as garantit qu'une seule vérification de type sera effectuée. Vous pourriez penser "mais il doit faire une vérification nulle au lieu d'une deuxième vérification de type", mais la vérification nulle est très efficace et performante par rapport à la vérification de type.

if (x is SomeType )
{
  SomeType y = (SomeType )x;
  // Do something
}

effectue 2x contrôles, tandis que

SomeType y = x as SomeType;
if (y != null)
{
  // Do something
}

fait 1x - la vérification nulle est très bon marché par rapport à une vérification de type.

12
STW

Il permet des vérifications rapides sans surcharge try/cast, ce qui peut être nécessaire dans certains cas pour gérer les arbres d'héritage basés sur les messages.

Je l'utilise beaucoup (entrer dans un message, réagir à des sous-types spécifiques). Try/cast serait beaucoup plus lent (beaucoup de frames try/catch à chaque message traversant) - et nous parlons ici de gérer 200.000 messages par seconde.

7
TomTom

Je choisis généralement l'un ou l'autre en fonction de la sémantique du code.

Par exemple, si vous avez un object que vous savez que ce doit être un string alors utilisez (string) parce que cela exprime que la personne qui écrit le code est sûre que l'objet est un string et si ce n'est pas le cas, nous avons déjà des problèmes plus importants que l'exception de cast d'exécution qui sera levée.

Utilisez as si vous n'êtes pas sûr que l'objet est d'un type spécifique mais souhaitez avoir une logique pour quand il l'est. Vous pouvez utiliser l'opérateur is suivi d'un transtypage, mais l'opérateur as est plus efficace.

2
João Angelo

Permettez-moi de vous donner des scénarios du monde réel où vous utiliseriez les deux.

public class Foo
{
  private int m_Member;

  public override bool Equals(object obj)
  {
    // We use 'as' because we are not certain of the type.
    var that = obj as Foo;
    if (that != null)
    {
      return this.m_Member == that.m_Member;
    }
    return false;   
  }
}

Et...

public class Program
{
  public static void Main()
  {
    var form = new Form();
    form.Load += Form_Load;
    Application.Run(form);
  }

  private static void Form_Load(object sender, EventArgs args)
  {
    // We use an explicit cast here because we are certain of the type
    // and we want an exception to be thrown if someone attempts to use
    // this method in context where sender is not a Form.
    var form = (Form)sender;

  }
}
2
Brian Gideon

Peut-être que des exemples aideront:

// Regular casting
Class1 x = new Class1();
Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2

// Casting with as
Class2 y = x as Class2; // Sets y to null if it can't be casted.  Does not work with int to short, for example.

if (y != null)
{
  // We can use y
}

// Casting but checking before.
// Only works when boxing/unboxing or casting to base classes/interfaces
if (x is Class2)
{
  y = (Class2)x; // Won't fail since we already checked it
  // Use y
}

// Casting with try/catch
// Works with int to short, for example.  Same as "as"
try
{
  y = (Class2)x;
  // Use y
}
catch (InvalidCastException ex)
{
  // Failed cast
}
0
Nelson Rothermel