Dois-je utiliser .ToString () lors de la concaténation de variables chaîne et entier en C #?


19
int a = 1;
int b = 2;
int sum = a + b;
string expression = "Expression: " + a + " + " + b + " = " + sum;
Console.WriteLine(expression); //displays Expression 1 + 2 = 3

Dois-je utiliser:

string expression = "Expression: " + a + " + " + b + " = " + sum;

ou

string expression = "Expression: " + a.ToString() + " + " + b.ToString() + " = " + result.ToString();

Est-il recommandé d'utiliser ToString()lors de la concaténation stringet int?


6
Dans a + "" + b + ""ou "" + a + b + "", peu importe: tout est concaténation de chaînes. En a + b + ""cela importe: aet bsont ajoutés en premier.
Tim S.

4
Note latérale: Dans VB.NET, cette ambiguïté est évitée en ayant un opérateur de concaténation de chaîne explicite : "Expression: " + alancera une erreur de temps de compilation (avec Option Strict On), "Expression: " & aeffectuera la concaténation de chaîne.
Heinzi

Le premier code entraînera la boxe (int à Int32), le second non. Le second est évidemment plus rapide.
Alphabets aléatoires

Réponses:


33

ToString usage

Non, vous ne devriez pas l'utiliser ToStringici.

La concaténation de chaînes transforme automatiquement les non-chaînes en chaînes, ce qui signifie que vos deux variantes sont presque¹ identiques:

Lorsqu'un ou les deux opérandes sont de type chaîne, les opérateurs d'addition prédéfinis concaténent la représentation sous forme de chaîne des opérandes.

Source: Spécification du langage C #: opérateur d'addition, MSDN .

Par contre, le premier (sans ToString):

  • Est plus court à écrire,
  • Est plus court à lire,
  • Est plus facile à entretenir et:
  • montre exactement l'intention de l'auteur: concaténer des chaînes.

Alors préférez le premier.

Sous la capuche

Ce qui est aussi intéressant, c'est de voir ce qui se passe sous le capot. Une des façons de le voir est de regarder le code IL dans LINQPad. Ce programme:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = a + b;
    Console.WriteLine(c);
}

est traduit dans l'IL suivant:

IL_0001:  ldc.i4.3    
IL_0002:  stloc.0     // a
IL_0003:  ldstr       " Hello"
IL_0008:  stloc.1     // b
IL_0009:  ldloc.0     // a
IL_000A:  box         System.Int32
IL_000F:  ldloc.1     // b
IL_0010:  call        System.String.Concat
IL_0015:  stloc.2     // c
IL_0016:  ldloc.2     // c
IL_0017:  call        System.Console.WriteLine

Tu vois ça System.String.Concat? Cela signifie que le code d'origine peut également être écrit comme cela, ce qui se traduit exactement par le même IL:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = string.Concat(a, b); // This is the line which was changed.
    Console.WriteLine(c);
}

Lorsque vous lisez la documentation destring.Concat(object[]) , vous pouvez apprendre que:

La méthode concatène chaque objet dans args en appelant la ToStringméthode sans paramètre de cet objet; il n'ajoute aucun délimiteur.

Cela signifie que ToStringc'est redondant. Aussi:

String.Empty est utilisé à la place de tout objet nul dans le tableau.

Ce qui gère bien le cas où certains des opérandes sont nuls (voir la note de bas de page 1).

Alors que dans le dernier exemple, la concaténation a été traduite en string.Concat, il convient également de mettre en évidence les optimisations du compilateur:

var a = "Hello " + "World";

se traduit par:

ldstr       "Hello World"
stloc.0

D'autre part:

var a = string.Concat("Hello ", "World");

se traduit par:

ldstr       "Hello "
ldstr       "World"
call        System.String.Concat
stloc.0

Autres alternatives

Il existe bien sûr d'autres façons de concaténer des représentations de chaîne d'objets en C #.

  1. StringBuilderest utilisé lorsque vous devez effectuer de nombreuses opérations de concaténation et permet de réduire le nombre de chaînes intermédiaires créées. Décider si vous devez utiliser une StringBuilderconcaténation ou une concaténation ordinaire peut ne pas être facile. Utilisez un profileur ou recherchez des réponses pertinentes sur Stack Overflow.

    L'utilisation StringBuildera un inconvénient majeur de rendre le code difficile à lire et à maintenir. Pour des cas simples comme celui de votre question, StringBuildernon seulement nuit à la lisibilité du code, mais aussi inutile en termes de performances.

  2. string.Join doit être utilisé lorsque vous devez ajouter des délimiteurs.

    Évidemment, ne jamais utiliser string.Joinavec un délimiteur vide pour concaténer des chaînes.

  3. string.Formatpeut être utilisé lorsque le modèle de chaîne est préféré à la concaténation de chaîne. L'un des cas où vous préférerez peut-être que le message peut être localisé, comme suggéré dans la réponse de kunthet.

    L'utilisation string.Formatprésente plusieurs inconvénients, ce qui la rend inadaptée à des cas simples comme le vôtre:

    • Avec de simples espaces réservés "{0}", il est souvent difficile de savoir quel paramètre va où. Il est fréquent d'inverser par erreur les paramètres ou d'en oublier un. Heureusement, C # 6 introduit enfin l' interpolation de chaînes qui résout ce problème.

    • Les performances d'exécution peuvent se dégrader. Bien sûr, ne présumez pas que string.Formatc'est toujours plus lent. Si les performances sont importantes, mesurez deux approches et déterminez laquelle est la plus rapide en fonction de vos résultats réels au lieu d'hypothèses.

    • Le code est légèrement plus long à écrire, plus long à lire et plus difficile à maintenir, bien que cela soit extrêmement mineur et ne devrait pas trop vous déranger.


¹ La différence apparaît lorsque l'un des objets l'est null. Sans ToString, a nullest remplacé par une chaîne vide. Avec ToString, un NullReferenceExceptionest lancé.


1
Pour exactement cette raison (comportement imprévisible), la concaténation de chaînes avec le +est considérée comme une mauvaise pratique dans la plupart des langues. Dans ce cas string.Concat, j'utiliserais , dans de nombreux cas, string.Formatc'est mieux. Ce n'est certainement pas Pythonic à utiliser +, et puisque PEP 3101 %est également déconseillé str.format.
Arda Xi

2
Substitue-t-on nullvraiment une chaîne vide pour vraiment "la gérer correctement"? Eh bien, ce n'est pas aussi mauvais que "en cas d'erreur reprendre ensuite" ...
Deduplicator

Sous le capot, si vous concaténez sans appeler .ToString (), la boxe se produira ..., et Concat(object[])sera utilisée à la place de Concat(string[]). Donc, "string " + in'est pas réellement identique à"string " + i.ToString()
Alphabets aléatoires

@RandomAlphabets: point valide. Cependant, la différence est simplement l'emplacement de ToString(): le code OP dans un cas, System.String.Concatl'implémentation de dans l'autre cas. Donc, la réponse reste valable: n'écrivez pas le code qui n'a aucun avantage.
Arseni Mourzenko

15

Au lieu de cela, vous devez utiliser le formateur de chaînes. Il est plus facile de formater votre nombre en représentation sous forme de chaîne ou en localisation. par exemple:

string expression = string.Format("Expression: {0} + {1} = {2}", a, b, sum);

Plus d'informations sur MSDN .

Cependant, le formateur de chaînes est moins lisible (et peut-être aussi les performances) que la concaténation de chaînes.


6
Voulez-vous expliquer pourquoi cette option est meilleure?
World Engineer

@WorldEngineer: J'ai mis à jour l'explication.
kunthet

12
Je ne sais pas pour tout le monde, mais je trouve cela plus lisible. Peut-être parce que j'ai grandi avec C où s [n] printf est la seule option réaliste pour ce type de code.
Jules

2
Mais cette façon donne trois sources d'erreurs au lieu d'une. Lorsque vous ajoutez quelque chose dans la chaîne, 1) vous devez changer la chaîne de format, 2) ne pas oublier d'ajouter un nouveau paramètre dans la liste, 3) essayer de choisir le bon endroit dans la liste où le nouveau paramètre doit être placé.
Ruslan

2
Je veux juste sonner et vous informer de la prochaine fonction d'interpolation de chaînes en C # 6. Vous écrirez "Expression: \ {a} + \ {b} = \ {sum}" pour obtenir le même résultat. codeproject.com/Articles/846566/...
cwap

-2

Si vous utilisez la +concaténation, elle utilise elle-même la String.Concatméthode. La chaîne elle-même n'expose pas d'opérateur +.

par exemple:

int i = 10;
string str = "hello" + i;

est compilé en:

int i = 10;
object o1 = "hello";
object o2 = i; // Note boxing
string str = string.Concat(o1, o2);

Si vous appelez directement ToString, cela évitera la boxe et appellera la Concat(string, string)surcharge. Par conséquent, l' ToStringappel sera légèrement plus efficace mais pas suffisamment significatif. Vous feriez mieux d'aller avec l'exemple qui vous semble plus lisible.


2
cela semble simplement répéter les points soulevés et expliqués dans la réponse précédente : "La concaténation de chaînes transforme automatiquement les non-chaînes en chaînes ..."
gnat
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.