Introduction : quand le code commence à "se tordre"
\n\nImaginez : vous écrivez en C#, vous devez afficher un message comme Valeur : {42}. Vous utilisez String.Format("Valeur : {0}", 42) — et vous obtenez le résultat attendu. Maintenant, essayez d'afficher simplement {42} sans substitution. En écrivant naïvement :
string result = String.Format("{{42}}");\n\nVous vous attendez à voir {42}, mais à la place, vous obtenez une erreur de format ou une chaîne vide. Cela vous dit quelque chose ? Cette question est l'une des plus populaires sur Stack Overflow avec des milliers de vues. Et aujourd'hui, nous ne nous contenterons pas de donner la réponse, nous allons regarder sous le capot de .NET pour comprendre comment fonctionne l'échappement des accolades en C#. C'est parti !
Le problème : pourquoi {{ ne fonctionne-t-il pas comme dans d'autres langages ?
\n\nEn C#, les accolades {} sont des caractères spéciaux dans les chaînes de format. Elles indiquent où commence et où se termine un espace réservé pour la substitution d'une valeur. Par exemple, {0} signifie "insère ici le premier argument".
Mais que faire si nous devons afficher les accolades elles-mêmes en tant que texte ? Dans la plupart des langages (Python, Java), l'échappement fonctionne par doublement : {{ donne {. En C#, la logique est la même, mais avec un piège : deux accolades ouvrantes {{ se transforment en une seule {, mais seulement si elles ne font pas partie d'un espace réservé valide.
Exemple concret : vous écrivez un générateur de code en C# et devez afficher la chaîne if (x > 0) { return x; }. Si vous écrivez simplement :
string template = "if (x > 0) { return x; }";\n\nLe compilateur ou String.Format interprétera { return x; } comme une tentative de formatage et lèvera une exception FormatException.
La solution : échappement correct des accolades en C#
\n\nMéthode classique : String.Format et StringBuilder
\n\nLa règle est simple : pour afficher une accolade, écrivez-en deux à la suite.
\n\n// Affiche : {Hello World}\nstring result = String.Format("{{Hello World}}");\nConsole.WriteLine(result); // {Hello World}\n\nMais il y a une nuance : si vous devez utiliser à la fois des espaces réservés et des accolades échappées, l'ordre est important. D'abord l'échappement, ensuite la substitution :
\n\nint value = 42;\n// Affiche : Valeur {42} entre accolades\nstring result = String.Format("Valeur {{{0}}} entre accolades", value);\nConsole.WriteLine(result); // Valeur {42} entre accolades\n\nDécortiquons : {{{0}}} correspond à {{ (une accolade) + {0} (espace réservé) + }} (une accolade). Résultat : {42}.
Interpolation de chaînes ($"...") — approche moderne
\n\nDepuis C# 6, nous avons l'interpolation de chaînes. Ici, l'échappement fonctionne différemment — par doublement des accolades, mais sans espaces réservés à l'intérieur :
\n\nint value = 42;\n// Affiche : Valeur {42} entre accolades\nstring result = $"Valeur {{{value}}} entre accolades";\nConsole.WriteLine(result); // Valeur {42} entre accolades\n\nNotez : dans l'interpolation, {{ donne {, et {value} est une substitution. Tout fonctionne intuitivement si vous retenez la règle : deux accolades donnent une accolade.
Cas avancé : StringBuilder.AppendFormat
\n\nLorsque vous travaillez avec StringBuilder, utilisez la même syntaxe :
var sb = new StringBuilder();\nsb.AppendFormat("{{0}} = {0}", 123);\nConsole.WriteLine(sb.ToString()); // {0} = 123\n\nComment cela fonctionne sous le capot : analyse du mécanisme de formatage
\n\nRegardons dans les sources de .NET (elles sont ouvertes sur GitHub !). Lorsque vous appelez String.Format, la méthode FormatHelper est lancée en interne, itérant sur les caractères de la chaîne de format.