Suite à l'article sur la concaténation, nous avions vu qu'il est très important d'utiliser le StringBuilder pour une question de performance. Ici on verra comment formater une chaîne de caractères, une phrase, ce formatage est souvent utilisé.

Pourquoi le String Format ?

Je ne vais pas vous dire que c'est plus performant, au contraire le string.Format() coûte quelques millisecondes en plus selon un simple test par rapport à une phrase concaténée:

string nom = "Dupont";
string prenom = "Julie";
string adresse = "Rue de l'étoile";
string numero = "10";
string codePostal = "75000";
string ville = "Paris";

//J'utilise Stopwatch pour chonométrer mon code
Stopwatch s = new Stopwatch();
//Je démarre Stopwatch
s.Restart();
for(int i=0; i < 100000; i++)
{
string monMessage = string.Format("Bonjour {0} {1}, je vous écris pour vous demander de m'envoyez mon colis à {2}, {3} - {4} {5}", 
                                   nom, prenom, adresse, numero, codePostal, ville);
}
//Je stoppe Stopwatch
s.Stop();
//J'affiche le résultat
Console.WriteLine(String.Format("Temps: {0}", s.Elapsed));
s.Restart();
for(int i=0; i < 100000; i++)
{
string monMessage = "Bonjour " + nom + " " + prenom + ", je vous écris pour vous demander de m'envoyer mon colis à " + 
                     adresse + ", " + numero + " - " + codePostal + " " + ville;
}
s.Stop();
Console.WriteLine(String.Format("Temps: {0}", s.Elapsed));

//Résultat:
//string.format -> Temps: 00:00:00.0378547
//concatènation -> Temps: 00:00:00.0134245

La deuxième partie du code est moins lisible que la première partie du code, avez-vous remarqué qu'on utilise string.Format() au lieu de concaténer les variables (par des +) ?

Le string.Format() est une bonne habitude à prendre, c'est beaucoup plus lisible, mais vous verrez plus loin qu'on peut gérer le format de sortie de la chaîne de caractère.

Comme on peut le voir, il suffit de mettre entre accolade (ou crochet) {x} l'indice de la valeur qui sera remplacée, attention ceci:

int i = 0;
int x = 100;
string.Format("Ma Valeur est {0}, par contre x est égale à {1}", i, x);

//Résultat:
//Ma Valeur est 0, par contre x est égale à 100

//N'est pas la même chose que ceci:

string.Format("Ma Valeur est {1}, par contre x est égale à {0}", i, x);
//Résultat:
//Ma Valeur est 100, par contre x est égale à 0

Dans l'exemple ci-dessus, à la seconde ligne, le premier indice est {1}, il ne va pas donc prendre i, parce que i est en position zéro (et oui dans l'informatique, on commence toujours par zéro et non par 1), la position à {1} est x, tandis que l'indice {0} est la valeur de la position zéro donc i.

Vous avez compris ?

Je résume, il faut éviter les concaténations de ce genre:

string nom = "Dupont";
string prenom = "Julie";
string adresse = "Rue de l'étoile";
string numero = "10";
string codePostal = "75000";
string ville = "Paris";
string monMessage = "Bonjour " + nom + " " + prenom + ", je vous écris pour vous demander de m'envoyer mon colis à " + 
                                      adresse + ", " + numero + " - " + codePostal + " " + ville;
Console.WriteLine(monMessage);

//Résultat:
//Bonjour Dupont Julie, je vous écris pour vous demander de m'envoyer mon colis à Rue de l'étoile, 10 - 75000 Paris

Mais plutôt:

string nom = "Dupont";
string prenom = "Julie";
string adresse = "Rue de l'étoile";
string numero = "10";
string codePostal = "75000";
string ville = "Paris";
string monMessage = string.Format("Bonjour {0} {1}, je vous écris pour vous demander de m'envoyez mon colis à {2}, {3} - {4} {5}", 
                                    nom, prenom, adresse, numero, codePostal, ville);
Console.WriteLine(monMessage);

//Résultat:
//Bonjour Dupont Julie, je vous écris pour vous demander de m'envoyer mon colis à Rue de l'étoile, 10 - 75000 Paris

Autre avantage

Là ça commence à devenir plus intéressant, grâce au string.Format(), nous pouvons formater directement une valeur, comme ceci:

int salaire = 1000;
int heureDeTravail = 16;
string monMessage = string.Format("Mon patron me paye {0:0.00}€ par mois pour {1:0#} h de travail par jour.", salaire, heureDeTravail);
Console.WriteLine(monMessage);
//Mon patron me paye 1000,00€ par mois pour 16 h de travail par jour.

heureDeTravail = 1;
monMessage = string.Format("Mon patron me paye {0:0####.00}€ par mois pour {1:0#} h de travail par jour.", salaire, heureDeTravail);
Console.WriteLine(monMessage);
//Mon patron me paye 01000,00€ par mois pour 01 h de travail par jour.

monMessage = string.Format("Nous sommes le {0}", DateTime.Now);
Console.WriteLine(monMessage);
//Nous sommes le 23-04-19 16:53:54

monMessage = string.Format("Nous sommes le {0:dd-MM-yyyy}", DateTime.Now);
Console.WriteLine(monMessage);
//Nous sommes le 23-04-2019

Comme on peut le voir, on peut directement formater la valeur comme on le désire directement, ce qui serait plus long lors de concaténation.

Un autre avantage, c'est lorsque vous prenez une phrase dans une base de données ou dans un fichier de ressource, mais que cette phrase doit à chaque fois contenir des valeurs différentes, il suffit de la formater comme cela:

//Ici on prend une phrase dans un fichier de ressource ou même une base de données
//peu importe ou la phrase vient, c'est juste un exemple
string.Format(resource.GetString("MaPhraseDansMonFichierDeRessource"), adresse, codePostal, ville);

//MaPhraseDansMonFichierDeRessource = "J'habite à {0}, code postal {1}, ville {2}"

Variante courte

Il y a une version encore plus courte du string.Format() en C# 6 (Roslyn) à partir de Visual Studio 2015 (il faut ajouter le package Microsoft.Net.Compilers pour utilisez les nouvelles fonctionnalités C#):

string monMessage = string.Format("Nous sommes le {0:dd-MM-yyyy}", DateTime.Now);
Console.WriteLine(monMessage);
//Résultat: Nous sommes le 23-04-2019

monMessage = $"Nous sommes le {DateTime.Now:dd-MM-yyyy}";
Console.WriteLine(monMessage);
//Résultat: Nous sommes le 23-04-2019

La 2eme ligne présente un string.Format() un peu différent, on commence par le signe $ (dollars) et ensuite l'indice qui était zéro dans la première ligne est directement remplacée et placée entre les accolades.

Spécificateur de format Description Exemples Résultat
C ou c Devise string s = $"{2.5:C}";

string s = $"{-2.5:C}";
$2.50

($2.50)
D ou d Décimal string s = $"{25:D5}"; 00025
E ou e Exponentiel string s = $"{250000:E2}"; 2.50E+005
F ou f Virgule fixe string s = $"{2.5:F2}";

string s = $"{2.5:F0}";
2.50

3
G ou g Général string s = $"{2.5:G}"; 2.5
N ou n Numérique string s = $"{2500000:N}"; 2,500,000.00
P ou p Pourcentage string s = $"{0.25:P}"; 25.00%
R ou r Aller-retour string s = $"{2.5:R}"; 2.5
X ou x Hexadécimal string s = $"{250:X}";

string s = $"{0xffff:X}";
FA

FFFF

Et bien d'autres encore !

Pour plus de renseignements sur le string.Format(), il y a ici la documentation sur le site de Microsoft: https://docs.microsoft.com/fr-FR/dotnet/api/system.string.format?redirectedfrom=MSDN&view=netframework-4.8#System_String_Format_System_String_System_Object_

A la compilation, ça ne change rien, le signe dollars est transformé par un string.Format(), c'est juste une question d'habitude, mais je trouve cela encore plus lisible !