30 votes

Utilisation du ternaire C# avec String.Equals

Ça marche :

short value;
value = 10 > 4 ? 5 : 10;

Ça marche :

short value;
value = "test" == "test" ? 5 : 10;

Ça ne marche pas :

short value;
string str = "test";
value = "test" == str ? 5 : 10;

Ceci non plus :

short value;
string str = "test";
value = "test".Equals(str) ? 5 : 10;

Dans les deux derniers cas, j'obtiens l'erreur suivante :

Cannot implicitly convert type 'int' to 'short'.
An explicit conversion exists (are you missing a cast?)

Pourquoi dois-je lancer sur les deux derniers cas et non sur les deux premiers ?

42voto

Timothy Shields Points 17970
short value;
value = 10 > 4 ? 5 : 10;             //1
value = "test" == "test" ? 5 : 10;   //2
string str = "test";
value = "test" == str ? 5 : 10;      //3
value = "test".Equals(str) ? 5 : 10; //4

Les deux dernières expressions ternaires (3,4) ne peuvent pas être résolues en une constante au moment de la compilation. Le compilateur traite donc l'expression 5 y 10 comme int et le type de l'expression ternaire entière est int . Pour convertir un int à un short nécessite un moulage explicite.

Les deux premières expressions ternaires (1,2) puede être résolu en une constante au moment de la compilation. La valeur de la constante est un int mais le compilateur sait qu'elle s'insère dans un fichier short et ne nécessite donc aucun moulage.

Pour le plaisir, essayez ceci :

value = "test" == "test" ? 5 : (int)short.MaxValue + 1;

4voto

Falanwe Points 2366

Vous avez besoin d'un casting pour faire fonctionner les deux derniers exemples.

value = (short)("test" == str ? 5 : 10);

Pourquoi n'en avez-vous pas besoin dans les deux premiers ?

Parce que les deux premiers sont des constantes de compilation. Le compilateur est capable de traduire 10 > 4 ? 5 : 10 a true ? 5 : 10 puis à juste 5

Donc quand vous écrivez

value = 10 > 4 ? 5 : 10;

C'est effectivement la même chose que

value = 5;

qui compile parce que le compilateur est autorisé à caster implicitement les constantes si elles sont dans la plage autorisée.

Inversement, "test" == str ? 5 : 10; n'est pas une constante de temps de compilation, donc la compilation n'est pas autorisée à l'intégrer de manière implicite. Vous devez faire un cast explicite vous-même.

3voto

Jeppe Stig Nielsen Points 17887

Ceci est défini par la spécification du langage C#, bien sûr.

Ce qu'il faut savoir, c'est qu'il existe deux types de conversions. de int à short . L'un est un explicite conversion qui s'applique toujours mais qui nécessite d'écrire (short) explicitement avant le int expression. L'autre est une conversion d'une expression constante implicite qui ne s'applique que lorsque (a) le site int est une constante de temps de compilation et (b) la valeur de cette expression du temps de compilation est comprise dans l'intervalle d'un short c'est-à-dire -32768 par le biais de 32767 .

Un littéral comme 5 , 10 o 4 a un type int en C# (cela s'applique à tout entier littéral qui se trouve entre -2147483648 y 2147483647 et non suivi d'un symbole L , U ou similaire). Ainsi, si nous regardons les côtés droits de toutes vos missions, ils sont clairement int des expressions, et non short .

Dans l'affaire 10 > 4 ? 5 : 10 puisque 10 y 4 sont des constantes de compilation, c'est la même chose que true ? 5 : 10 parce que le > opérateur entre int s est intégré et donnera une constante lorsque les opérandes sont des constantes. Et de la même manière true ? 5 : 10 donne 5 car les trois opérandes sont des constantes, et ?: est classé lui-même comme une constante dans ce cas. Donc ça dit vraiment :

short value = 5;

où le " 5 "est une constante de compilation. Par conséquent, il est vérifié au moment de la compilation si l'élément int 5 se situe dans la fourchette (cela n'a pas d'importance avec l'option 10 il pourrait être 999999 ), et puisque c'est le cas, l'option conversion d'une expression constante implicite s'applique, et c'est légal.

Notez que vous pouvez faire la même chose avec :

const int huge = 10;
const int tiny = 4;
const int significant = 5;
const int unimporatnt = 10;
short value;
value = huge > tiny ? significant : unimportant;

tant que tous les opérandes sont const variables (jeu de mots ?).

Maintenant, si j'ai réussi à rendre l'explication claire, vous savez aussi maintenant que l'obstacle empêchant value = "test" == str ? 5 : 10; de fonctionner est que vous n'avez pas marqué le str local comme const . Faites-le, et il sera autorisé.

Avec le Equals la situation est un peu plus grave. Le résultat d'un appel à Equals n'est jamais considérée comme une constante de temps de compilation (et je ne pense pas qu'elle soit "optimisée" loin de là, par exemple "same".Equals("same") appellera effectivement la méthode au moment de l'exécution). La même chose se produirait avec (10).Equals(4) o (10).CompareTo(4) > 0 et ainsi de suite, les cordes ne sont donc pas spéciales à cet égard.


Vous savez probablement déjà que lorsque

short value = cond ? 5 : 10;

n'est pas autorisé car cond n'est pas une constante de temps de compilation, vous utilisez simplement la conversion explicite à la place, donc écrivez :

short value = cond ? (short)5 : (short)10;

ou :

short value = (short)(cond ? 5 : 10);

Techniquement, ils ne sont pas identiques, puisque le premier n'a pas de conversion de restriction au moment de l'exécution (les expressions (short)5 y (short)10 sont des littéraux de type short ), tandis que le dernier doit convertir un fichier int a short au moment de l'exécution (ce qui est bien sûr moins cher qu'incroyablement bon marché).


Les autres réponses (non supprimées !) sont correctes, ce n'est qu'une information supplémentaire.

2voto

Le fait est que 10 > 4 ? 5 : 10; est en fait converti en une constante au moment de la compilation, avant qu'un casting de type ne soit nécessaire. Cela signifie que le compilateur s'est rendu compte que l'instruction turnary peut être réduite à une constante avant même qu'un casting de type implicite ne soit nécessaire pour la compilation. Donc, en d'autres termes, cette expression est la même que :

value = 5;

Dans les deux dernières déclarations, ce n'est pas vrai puisque vous utilisez une variable pour retenir les valeurs pour vous et non une constante. Le compilateur ne vérifie pas la valeur réelle de la variable pour voir s'il peut réduire l'expression à une constante. Vous avez donc besoin du casting.

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