Raw String Literals، روشی ساده جهت تعریف یک قطعهی متنی، بدون نیاز به escapeهای فراوان و یا تعریف ""های متعدد است؛ برای مثال نوشتن رشتههای تشکیل شدهی از محتوای XML و یا JSON. به این صورت تعریف رشتههای پیچیده، سادهتر شده و قابلیت نگهداری آنها، بهبود خواهد یافت. Raw String Literal با حداقل سه عدد " متوالی، شروع شده و با حداقل سه عدد " متوالی، خاتمه پیدا میکنند:
string name = "Vahid", country = "Iran";
string jsonString =
$$"""
{
"Name": {{name}},
"Country": {{country}}
}
""";
Console.WriteLine(jsonString);
بدون وجود این قابلیت، معادل واقعی رشتهی فوق را باید به صورت زیر تشکیل داد:
"{\r\n \"Name\": Vahid,\r\n \"Country\": Iran\r\n}"
و یا امکان درج سادهتر عبارات XML، بدون نیاز به escape قسمتی از آن:
string html =
"""
<body style="normal">
<div class="book-content">
This is information about the "C# 11" book.
</body>
<footer>
This is information about the author of the "C# 11" book.
</footer>
</element>
""";
سؤال: اگر در محتوای Raw String Literal تعریف شده، نیاز به سه عدد " متوالی وجود داشت، چه باید کرد؟
اگر به توضیحات فوق دقت کنید، عنوان شد که شروع و پایان Raw String Literals، با «حداقل» سه عدد " همراه است و به این صورت پیاده سازی میشود:
- اگر رشتهی شما نیاز به سه "" متوالی داشت، باید raw string literal را با حداقل چهار " شروع و خاتمه دهید.
- اگر رشتهی شما نیاز به چهار "" متوالی داشت، باید raw string literal را با حداقل پنج " شروع و خاتمه دهید.
و ... به همین ترتیب برای مابقی حالات.
var text1 = """" Hello World! """ """";
var text2 = """"" Hello World! """" """"";
کاهش فواصل سمت چپ رشتهها، با استفاده از Raw string literals
به مثال زیر که یک قطعه چند سطری SQL را به دو روش قدیم و جدید تعریف میکند، دقت کنید (فواصل سمت چپ در این مثال مهم هستند):
var sql1 =
@"
SELECT Name
FROM Customers
WHERE id = @id
";
Console.WriteLine(sql1);
var sql2 =
"""
SELECT Name
FROM Customers
WHERE id = @id
""";
Console.WriteLine(sql2);
آیا خروجی نمایشی این دو، یکی است؟
پاسخ: خیر! خروجی نمایشی این دو به صورت زیر است:
SELECT Name
FROM Customers
WHERE id = @id
SELECT Name
FROM Customers
WHERE id = @id
در اینجا به فواصل سمت چپ رشتهها دقت کنید. همیشه فرمت کردن
verbatim strings در زبان #C مشکل بودهاست و در حین تعریف عبارات چند سطری، تنظیم فواصل سمت چپ، مساله ساز است. اما این مشکل با raw string literals وجود ندارد. در این حالت فقط کافی است رشتهی مدنظر را دقیقا ذیل جائیکه """ را تعریف کردهاید، شروع کنید (ستون شروع آنها یکی باشد). به این ترتیب تمام فواصل سمت چپ آن، ندید گرفته میشوند.
خروجی واقعی رشتهی sql1 به صورت زیر است:
"\r\n SELECT Name\r\n FROM Customers\r\n WHERE id = @id\r\n "
و رشتهی sql2 به این نحو تفسیر میشود (که حتی فواصل ابتدا و انتهای آن نیز Trim شدهاند):
"SELECT Name\r\nFROM Customers\r\nWHERE id = @id"
استفاده از string interpolation در raw string literals
همیشه عبارات ما از رشتههای ثابت تشکیل نمیشوند. در این بین همواره نیاز به interpolation با مقادیر ثابت و یا متغیرها وجود خواهد داشت. انجام چنین کاری با raw string literals هم میسر است:
var name = "Vahid";
var text =
$"""
Hello {name1}!
Welcome to the Team!
""";
سؤال: اگر در این مثال نیاز بود تا از {} جهت مقاصد نمایشی استفاده شود، چه باید کرد؟ یعنی نیاز به درج {} صرفا متنی وجود داشت.
پاسخ: در اینجا تنها کاری را که باید انجام داد، استفاده از یک $ اضافهتر در ابتدای interpolated string است (مانند مثال ابتدای بحث):
var name1 = "Vahid";
var text =
$$"""
Hello {{{name1}}}!
Welcome to the Team!
""";
که در نهایت، معادل با رشتهی خروجی زیر است:
"Hello {Vahid}!\r\n\r\nWelcome to the Team!"
سؤال: اگر در این مثال نیاز بود تا از {{{}}} جهت مقاصد نمایشی استفاده شود، چه باید کرد؟
پاسخ: باید تعداد $های ابتدای رشته را افزایش داد. برای مثال اگر نیاز به درج سه { متوالی است، باید از 4 عدد $ در ابتدای رشته استفاده کرد:
var name4 = "Vahid";
var text4 =
$$$$"""
Hello {{{{{{{name4}}}}}}}!
Welcome to the Team!
""";
که خروجی آن، معادل رشتهی نهایی زیر است:
"Hello {{{Vahid}}}!\r\nWelcome to the Team!"
بنابراین تعداد $ مشخص میکند که چه تعداد از {{ها میتوانند بدون اینکه عبارت interpolation را تشکیل دهند، در رشته حضور داشته باشند. برای مثال تمام ترکیبهای زیر یک خروجی را دارند و آن هم همان name تعریف شدهاست:
string name = "Vahid";
var text1 = $"{name}";
var text2 = $"""{name}""";
var text3 = $$"""{{name}}""";
var text4 = $$$"""{{{name}}}""";
var text5 = $$$$"""{{{{name}}}}""";
در مثال فوق، تعداد $ها با تعداد جفتهای {} یکی است. بنابراین تنها به عنوان یک interpolation expression delimiter تفسیر میشوند.
اما در مثال زیر، تعداد $ها با تعداد {}ها یکی نیست؛ برای مثال اگر از دو $ ابتدایی استفاده شود، ذکر یک جفت تکی {}، تنها به معنای وجود کاراکتری آنها است و همینطور اگر از سه $ ابتدایی استفاده شود، ذکر یک جفت دو تایی {{}}، تنها به معنای وجود کاراکتری آنها است و همینطور الی آخر. اما اگر معادل تعداد $ها، از جفتهای {} استفاده شود، تمام آنها با هم فقط یک interpolation expression delimiter را تشکیل میدهند.
string name = "Vahid";
var text6 = $$"""{name}"""; // = "{name}"
var text7 = $$"""{{{name}}}"""; // = "{Vahid}"
var text8 = $$$"""{{name}}"""; // = "{{name}}"
var text9 = $$$"""{{{{{name}}}}}"""; // = "{{Vahid}}"
var text10 = $$$$"""{{{name}}}"""; // = "{{{name}}}"
var text11 = $$$$"""{{{{{{{name}}}}}}}"""; // = "{{{Vahid}}}"