27 votes

Pourquoi est implémenté en tant que?

Étant donné que cette très naturel de cas d'utilisation (si vous ne savez pas ce que fait réellement)

if (x is Bar) {
   Bar y = x as Bar;
   something();
}

est en fait l'équivalent (c'est à dire, généré par le compilateur, IL de le code ci-dessus sera équivalent) pour

Bar y = x as Bar;
if (y != null) {
    y = x as Bar; //The conversion is done twice!
    something();
}

EDIT:

Je suppose que je n'avais pas fait ma question claire. Je n'aurai plus jamais écrire le deuxième extrait que bien sûr, c'est redondant. Je suis en prétendant que le IL généré par le compilateur lors de la compilation de premier extrait est équivalente à la deuxième extrait, qui est redondante. Questions: a) Est-ce correct b) Si oui, pourquoi est est mis en œuvre comme cela?

Parce que j'ai trouver le premier extrait de code beaucoup plus clair et plus joli que l'réellement bien écrit

Bar y = x as Bar;
if (y != null) {
   something();
}

EDIT 2: Merci d'essayer d'éviter d'ajouter des guillemets pour le titre, si possible, merci!

CONCLUSION:

L'optimisation de l'est/de cas n'est pas le compilateur de la responsabilité, mais l'équipe de l'.

En outre, comme avec null check a de moins en moins (et moins cher) instructions que les deux alternatives (est et et est et de la distribution).

Addendum:

IL pour avec nullcheck (.NET 3.5):

L_0001: ldarg.1 
L_0002: isinst string
L_0007: stloc.0 
L_0008: ldloc.0 
L_0009: ldnull 
L_000a: ceq 
L_000c: stloc.1 
L_000d: ldloc.1 
L_000e: brtrue.s L_0019
L_0011: ldarg.0 
L_0019: ret

IL est et cast (.NET 3.5):

L_0001: ldarg.1 
L_0002: isinst string
L_0007: ldnull 
L_0008: cgt.un 
L_000a: ldc.i4.0 
L_000b: ceq 
L_000d: stloc.1 
L_000e: ldloc.1 
L_000f: brtrue.s L_0021
L_0012: ldarg.1 
L_0013: castclass string
L_0018: stloc.0 
L_0019: ldarg.0 
L_0021: ret

IL est et que (.NET 3.5):

L_0001: ldarg.1 
L_0002: isinst string
L_0007: ldnull 
L_0008: cgt.un 
L_000a: ldc.i4.0 
L_000b: ceq 
L_000d: stloc.1 
L_000e: ldloc.1 
L_000f: brtrue.s L_0021
L_0012: ldarg.1 
L_0013: isinst string
L_0018: stloc.0 
L_0019: ldarg.0 
L_0021: ret

Ceux-ci ont été modifiés pour la brièveté (déclarations de méthode, des opr et des appels à quelque chose() supprimé)

12voto

Eric Lippert Points 300275

a) Est-ce correct

Oui, si je l'ai déclaré dans l'autre sens. Vous dites que le "est" est un sucre syntaxique pour-suivie-par-null-case. J'aurais dit le contraire: que le "que" est un sucre syntaxique pour "vérifier le type de mise en œuvre, en fonte si le succès, la valeur null si échec".

C'est-à-dire, je serais plus enclin à dire

if (x is Bar) { 
   Bar y = x as Bar; 
   something(); 
} 

est en fait l'équivalent de

if (x is Bar) { 
   Bar y = (x is Bar) ? (Bar)x : (Bar) null; 
   something(); 
} 

Voir, vous souhaitez définir "comme" en termes de "est", et non pas l'inverse. La véritable question devrait être: "pourquoi est comme mis en œuvre est?" :-)

b) dans l'affirmative, pourquoi est implémenté comme ça?

Parce que c'est une bonne mise en œuvre de la spécification.

Je pense que je ne suis pas à la suite de votre ligne de la pensée ici. Est-il quelque chose de mal avec la mise en œuvre? Comment préféreriez-vous être mis en œuvre? Vous avez le "isinst" et "castclass" instructions à votre disposition; décrire les codegen de votre programme que vous souhaitez voir.

9voto

Damien_The_Unbeliever Points 102139

Ainsi, l'instruction IL est disponible (isinst) retourne un objet du type approprié, ou null si une telle conversion n'est pas possible. Et il ne jette pas une exception, si la conversion n'est pas possible.

Étant donné que, à la fois "est" et "comme" qui sont triviales à mettre en œuvre. Je ne prétends pas que "est" est mis en œuvre par "comme" dans ce cas, il suffit que le sous-jacent instruction IL permet à la fois de se produire. Maintenant, pourquoi le compilateur n'est pas capable d'optimiser le "est" suivi de "que" dans un seul isinst appel, c'est une autre affaire. Probablement, dans ce cas, c'est lié à portée variable (même si par moment c'est IL, la portée n'existe pas vraiment)

Modifier

En seconde opinion, vous ne pouvez pas optimiser "est" suivi de "que" dans un seul isinst appel, sans savoir que la variable en cours de discussion n'est pas l'objet de mise à jour à partir d'autres threads.

En supposant que x est une chaîne de caractères:

//Thread1
if(x is string)

//Thread2
x = new ComplexObject();

//Thread1
    y = x as string

Ici, y doit être null.

5voto

Will Vousden Points 13332

Dans votre exemple, l'utilisation de as est de toute façon redondante. Puisque vous savez déjà que x is Bar , vous devez utiliser un cast:

 if (x is Bar)
{
    Bay y = (Bar)x;
}
 

Alternativement, convertissez en utilisant as et vérifiez simplement null:

 Bar y = x as Bar;
if (y != null)
{

}
 

5voto

Steve Haigh Points 6261

Tout d'abord je suis en désaccord avec votre postulat qu'il est plus typique de cas d'utilisation. Il peut être votre préféré, mais l'idiomatiques approche est le "comme + null cochez la case" style:

Bar y = x as Bar; 
if (y != null) { 
   something(); 
}

Que vous avez trouvé le "est" approche requiert "que" ou un plâtre, c'est pourquoi le "comme" null " vérifier est la façon habituelle de faire cela dans mon expérience.

Je ne vois rien d'offensant à propos de ce "comme" approche, personnellement, je ne pense pas qu'elle soit plus désagréable à l'œil que n'importe quel autre code.

Quant à votre question, pourquoi l' is de mots clés mis en œuvre en termes de as mot-clé, je n'ai aucune idée, mais je n'aime pas le jeu de mots dans votre question:) je soupçonne qu'aucune n'est réellement mis en œuvre en termes de l'autre, mais l'outil (Réflecteur, je suppose) que vous avez utilisé pour générer des C# à partir de la IL a interprété le IL en termes de as.

2voto

J. Random Coder Points 686

Vous ne ferez pas un deuxième y = x as Bar; , car vous avez déjà y qui est Bar.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X