2010-08-31 19 views
2

Je suis à la recherche à un golf de code dans LINQPad et je me demandais pourquoi:comportement incompatible avec string + = int en C#

int c; 
string o; 

o+=c;//this works 

o+=P==2?"."+c:c;//this doesn't 

o+=P==2?"."+c:""+c;//this does 

surtout pourquoi le premier fonctionne et le second jette un « pas de conversion implicite entre ' chaîne 'et' int '"erreur.

Répondre

2

Votre deuxième exemple non fonctionnel présente des types incohérents dans l'opérateur ?:. Qu'est-ce que vous avez est:

o += (P == 2 ? (string) "." + c : (int) c); 

(Les types entre parenthèses ci-dessus sont là pour préciser ce que les existants types sont, ne pas les jeter à un autre type.)

Les deux côtés de la : en l'opérateur ternaire doit être du même type. Pour cette raison, votre deuxième exemple est une erreur de syntaxe. Le troisième exemple fonctionne car la concaténation avec une chaîne vide contraint c dans une chaîne.

+0

Ahh, merci. Je n'ai pas réalisé que les deux côtés devaient être du même type. Cela a du sens cependant. Je ne peux pas encore accepter une réponse, attendez quelques minutes. – 182764125216

+1

Ce n'est pas aussi strict que vous le dites. Il doit y avoir une conversion soit de la conséquence au type de l'alternative, soit de l'alternative au type de la conséquence. (Mais, s'ils diffèrent, pas les deux.) Le comportement ici est subtil; pour certaines de ces subtilités, voir mes articles sur le sujet: http://blogs.msdn.com/b/ericlippert/archive/tags/conditional+operator/ –

4

L'opérateur + sur les chaînes peut accepter un entier, ce qui entraîne une autre chaîne. Cependant, il n'y a pas de conversion implicite (ou explicite) de int en chaîne. Lorsque vous utilisez l'opérateur ternaire ?:, les deux branches doivent être du même type ou le type doit être implicitement convertible à l'autre.

Dans votre deuxième exemple, la première branche est une chaîne, une fois l'opérateur + terminé, mais le second est juste un int, donc cela ne fonctionne pas. Dans votre troisième exemple, les deux branches sont des chaînes, donc c'est bien.

+0

Donc, pour que votre deuxième réponse fonctionne, entrez: o + = P == 2? "." + C: c.ToString(); – Rudu

2

L'opérateur += utilise l'opérateur +, de sorte que le premier est vraiment:

o = o + c; 

Ce que le compilateur crée en fait est:

o = String.Concat((object)o, (object)c); 

L'entier est emballé, et la méthode Concat qui prend object paramètres est appelée. La méthode ToString sera appelée sur les deux paramètres pour obtenir leurs valeurs de chaîne, et elles sont concaténées.

Si vous commencez à convertir l'entier à une chaîne, le code est plus direct:

o += c.ToString(); 

qui devient:

o = String.Concat(o, c.ToString()); 

Dans le second code, les types de l'opérateur conditionnel doesn 't match:

bool ? string : int 

Les deuxième et troisième opérandes doivent avoir le même type, l IKE dans le troisième code:

bool ? string : string 

Le second code devient vraiment:

o = String.Concat(
    o, 
    P == 2 
    ? String.Concat((object)".", (object)c) 
    : c 
); 

et le troisième code devient vraiment:

o = String.Concat(
    o, 
    P == 2 
    ? String.Concat((object)".", (object)c) 
    : String.Concat((object)String.Empty, (object)c) 
); 

Quoi qu'il en soit, vous devriez envisager d'utiliser un StringBuilder pour construire chaînes au lieu d'utiliser l'opérateur +=:

StringBuilder builder = new StringBuilder; 

if (P == 2) { 
    builder.Append('.'); 
} 
builder.Append(c); 
+0

son dans un code de golf, de sorte que le but est de le faire fonctionner avec le moins de caractères possible. Je suis conscient que ce n'est pas le plus efficace à l'exécution. – 182764125216