مقدمة: عندما يبدأ الكود في "الانحناء"
\n\nتخيل: أنت تكتب بلغة C#، وتحتاج إلى عرض رسالة مثل القيمة: {42}. تستخدم String.Format("القيمة: {0}", 42) — وتحصل على النتيجة المتوقعة. والآن حاول عرض {42} فقط بدون استبدال. بكتابتك بسذاجة:
string result = String.Format("{{42}}");\n\nتتوقع رؤية {42}، ولكن بدلاً من ذلك تحصل على خطأ تنسيق أو سلسلة فارغة. مألوف؟ هذا السؤال هو من أكثر الأسئلة شيوعًا على Stack Overflow بآلاف المشاهدات. واليوم لن نقدم الإجابة فحسب، بل سننظر تحت غطاء .NET لفهم كيفية عمل هروب الأقواس المتعرجة في C#. هيا بنا!
المشكلة: لماذا لا يعمل {{ كما في اللغات الأخرى؟
\n\nفي C#، الأقواس المتعرجة {} هي رموز خدمية في سلاسل التنسيق. تشير إلى مكان بداية ونهاية العنصر النائب لاستبدال القيمة. على سبيل المثال، {0} يعني "أدخل الوسيطة الأولى هنا".
ولكن ماذا لو أردنا عرض الأقواس المتعرجة نفسها كنص؟ في معظم اللغات (Python، Java) يعمل الهروب من خلال المضاعفة: {{ يعطي {. في C# — نفس المنطق، ولكن مع خدعة: قوسان افتتاحيان {{ يتحولان إلى قوس واحد {، ولكن فقط إذا لم يكونا جزءًا من عنصر نائب صحيح.
مثال من الحياة الواقعية: أنت تكتب مولد كود بلغة C# وتحتاج إلى عرض السلسلة if (x > 0) { return x; }. إذا كتبت ببساطة:
string template = "if (x > 0) { return x; }";\n\nسيعتبر المترجم أو String.Format أن { return x; } محاولة تنسيق وسيرمي استثناء FormatException.
الحل: الهروب الصحيح للأقواس المتعرجة في C#
\n\nالطريقة التقليدية: String.Format و StringBuilder
\n\nالقاعدة بسيطة: لعرض قوس متعرج واحد، اكتب اثنين متتاليين.
\n\n// سيعرض: {Hello World}\nstring result = String.Format("{{Hello World}}");\nConsole.WriteLine(result); // {Hello World}\n\nولكن هناك فارق بسيط: إذا كنت بحاجة لاستخدام كل من العناصر النائبة والأقواس المهربة في نفس الوقت، فالترتيب مهم. أولاً الهروب، ثم الاستبدال:
\n\nint value = 42;\n// سيعرض: القيمة {42} بين قوسين متعرجين\nstring result = String.Format("القيمة {{{0}}} بين قوسين متعرجين", value);\nConsole.WriteLine(result); // القيمة {42} بين قوسين متعرجين\n\nدعنا نحللها بالتفصيل: {{{0}}} هي {{ (قوس واحد) + {0} (عنصر نائب) + }} (قوس واحد). النتيجة: {42}.
تضمين السلاسل ($"...") — النهج الحديث
\n\nابتداءً من C# 6، لدينا تضمين السلاسل. هنا يعمل الهروب بشكل مختلف — من خلال مضاعفة الأقواس، ولكن بدون عناصر نائبة بداخلها:
\n\nint value = 42;\n// سيعرض: القيمة {42} بين قوسين متعرجين\nstring result = $"القيمة {{{value}}} بين قوسين متعرجين";\nConsole.WriteLine(result); // القيمة {42} بين قوسين متعرجين\n\nلاحظ: في التضمين، {{ يعطي {، و {value} هو استبدال. كل شيء يعمل بشكل بديهي إذا تذكرت القاعدة: قوسان — قوس واحد.
حالة متقدمة: StringBuilder.AppendFormat
\n\nعند العمل مع StringBuilder، استخدم نفس الصيغة:
var sb = new StringBuilder();\nsb.AppendFormat("{{0}} = {0}", 123);\nConsole.WriteLine(sb.ToString()); // {0} = 123\n\nكيف يعمل هذا تحت الغطاء: تحليل آلية التنسيق
\n\nدعنا نلقي نظرة على المصادر المفتوحة لـ .NET (متاحة على GitHub!). عندما تستدعي String.Format، يتم تشغيل طريقة FormatHelper داخليًا، والتي تتكرر عبر أحرف سلسلة التنسيق.