Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Nota
Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.
Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut dicatat dalam catatan terkait rapat desain bahasa (LDM) .
Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .
Isu Utama: https://github.com/dotnet/csharplang/issues/8647
Ringkasan
Izinkan bentuk baru string harfiah yang dimulai dengan minimal tiga karakter """
(tetapi tidak maksimum), secara opsional diikuti oleh new_line
, konten string, dan kemudian berakhir dengan jumlah tanda kutip yang sama yang dimulai dengan literal. Misalnya:
var xml = """
<element attr="content"/>
""";
Karena konten berlapis mungkin ingin menggunakan """
maka pemisah awal/akhir dapat lebih panjang seperti:
var xml = """"
Ok to use """ here
"""";
Untuk membuat teks mudah dibaca dan memungkinkan indentasi yang disukai pengembang dalam kode, literal string ini akan secara alami menghapus indentasi yang ditentukan pada baris terakhir saat menghasilkan nilai harfiah akhir. Misalnya, harfiah formulir:
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
Akan berisi:
<element attr="content">
<body>
</body>
</element>
Ini memungkinkan kode terlihat alami, sambil tetap menghasilkan literal yang diinginkan, dan menghindari biaya runtime jika ini memerlukan penggunaan rutinitas manipulasi string khusus.
Jika perilaku indentasi tidak diinginkan, menonaktifkannya juga mudah dilakukan.
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
Formulir baris tunggal juga didukung. Ini dimulai dengan minimal tiga karakter """
(tetapi tidak maksimum), konten string (yang tidak dapat berisi karakter new_line
), dan kemudian diakhir dengan jumlah tanda kutip yang sama dengan yang dimulai dengan harfiah. Misalnya:
var xml = """<summary><element attr="content"/></summary>""";
String mentah yang diinterpolasi juga didukung. Dalam hal ini, string menentukan banyaknya kurung kurawal yang dibutuhkan untuk memulai interpolasi (yang ditentukan oleh jumlah tanda dolar yang ada pada awal literal). Urutan kurung kurawal apa pun dengan jumlah kurung kurawal yang kurang dari itu hanya dianggap sebagai konten. Misalnya:
var json = $$"""
{
"summary": "text",
"length" : {{value.Length}},
};
""";
Motivasi
C# tidak memiliki cara umum untuk membuat literal string sederhana yang dapat berisi berbagai teks secara efektif. Semua bentuk harfiah string C# saat ini membutuhkan beberapa bentuk pelepasan jika konten menggunakan beberapa karakter khusus (selalu jika pemisah digunakan). Hal ini mencegah mudahnya memiliki literal yang mengandung bahasa lain (misalnya, literal XML, HTML, atau JSON).
Semua pendekatan saat ini untuk membentuk harfiah ini di C# hari ini selalu memaksa pengguna untuk secara manual keluar dari konten. Pengeditan pada saat itu bisa sangat mengganggu karena pelepasan tidak dapat dihindari dan harus ditangani setiap kali muncul dalam konten. Ini sangat menyakitkan untuk regex, terutama ketika berisi tanda kutip atau garis miring terbelakang. Bahkan dengan string verbatim (@""
), tanda kutip itu sendiri harus di-escape, menghasilkan campuran C# dan regex yang saling terjalin.
{
dan }
juga sangat menjengkelkan dalam string interpolasi ($""
).
Inti permasalahannya adalah bahwa semua string kami memiliki pemisah awal/akhir yang tetap. Selama itu terjadi, kita harus selalu memiliki mekanisme pengecualian, karena konten string mungkin perlu menentukan pembatas akhir tersebut dalam konten. Ini sangat bermasalah karena pembatas "
sangat umum dalam banyak bahasa.
Untuk mengatasi hal ini, proposal ini memungkinkan pemisah awal dan akhir yang fleksibel sehingga mereka selalu dapat dibuat dengan cara yang tidak akan bertentangan dengan konten string.
Tujuan
- Berikan mekanisme yang memungkinkan semua nilai string disediakan oleh pengguna tanpa memerlukan urutan pelolosan apa pun. Karena semua string harus dapat direpresentasikan tanpa urutan escape, pengguna harus selalu dapat menentukan pembatas yang akan dijamin tidak bertabrakan dengan konten teks apa pun.
- Mendukung interpolasi dengan cara yang sama. Seperti di atas, karena semua string harus dapat diwakili tanpa escape, pengguna harus selalu dapat menentukan pemisah
interpolation
yang akan dijamin tidak bertabrakan dengan konten teks apa pun. Yang penting, bahasa yang menggunakan karakter pemisah interpolasi ({
dan}
) harus terasa kelas satu dan tidak menyulitkan untuk digunakan. - Literal string multibaris harus terlihat menyenangkan dalam kode dan tidak boleh membuat indentasi dalam unit kompilasi terlihat aneh. Yang penting, nilai harfiah yang sendiri tidak memiliki indentasi tidak boleh dipaksa untuk menempati kolom pertama file karena dapat memecah aliran kode dan akan terlihat tidak sejajar dengan sisa kode yang mengelilinginya.
- Perilaku ini harus mudah diubah sambil menjaga teks tetap jelas dan mudah dibaca.
- Untuk semua string yang tidak berisi
new_line
atau tidak dimulai maupun diakhiri dengan tanda kutip ("
), seharusnya mungkin untuk mewakili literal string itu sendiri pada satu baris.- Secara opsional, dengan kompleksitas ekstra, kita dapat menyempurnakan ini untuk menyatakan bahwa: Untuk semua string yang tidak berisi
new_line
(tetapi dapat dimulai atau diakhiri dengan karakter kutipan"
), harus dimungkinkan untuk mewakili string literal itu sendiri dalam satu baris. Untuk detail selengkapnya, lihat proposal yang diperluas di bagianDrawbacks
.
- Secara opsional, dengan kompleksitas ekstra, kita dapat menyempurnakan ini untuk menyatakan bahwa: Untuk semua string yang tidak berisi
Desain terperinci (kasus tanpa interpolasi)
Kami akan menambahkan produksi string_literal
baru dengan formulir berikut:
string_literal
: regular_string_literal
| verbatim_string_literal
| raw_string_literal
;
raw_string_literal
: single_line_raw_string_literal
| multi_line_raw_string_literal
;
raw_string_literal_delimiter
: """
| """"
| """""
| etc.
;
raw_content
: not_new_line+
;
single_line_raw_string_literal
: raw_string_literal_delimiter raw_content raw_string_literal_delimiter
;
multi_line_raw_string_literal
: raw_string_literal_delimiter whitespace* new_line (raw_content | new_line)* new_line whitespace* raw_string_literal_delimiter
;
not_new_line
: <any unicode character that is not new_line>
;
Pemisah akhir untuk raw_string_literal
harus cocok dengan pemisah awal. Jadi jika pemisah awal """""
pemisah akhir juga harus demikian.
Tata bahasa di atas untuk raw_string_literal
harus ditafsirkan sebagai:
- Ini dimulai dengan setidaknya tiga tanda kutip (tetapi tidak ada batas atas pada tanda kutip).
- Kemudian dilanjutkan dengan isi pada baris yang sama dengan tanda kutip awal. Konten ini pada baris yang sama dapat kosong, atau tidak kosong. 'blank' identik dengan 'sepenuhnya spasi kosong'.
- Jika konten pada baris yang sama tidak kosong, tidak ada konten lebih lanjut yang dapat diikuti. Dengan kata lain, literal harus diakhiri dengan jumlah tanda kutip yang sama pada baris yang sama.
- Jika konten pada baris yang sama kosong, maka literal dapat dilanjutkan dengan
new_line
dan dilanjutkan dengan beberapa baris konten berikutnya dannew_line
.- Baris konten adalah teks apa pun kecuali
new_line
. - Kemudian berakhir dengan sebuah
new_line
, beberapa angka (mungkin nol)whitespace
, dan jumlah tanda kutip yang sama dengan yang dimulai oleh literal.
- Baris konten adalah teks apa pun kecuali
Literal string nilai mentah
Bagian antara raw_string_literal_delimiter
awal dan akhir digunakan untuk membentuk nilai raw_string_literal
dengan cara berikut:
- Dalam kasus
single_line_raw_string_literal
, nilai harfiah akan persis menjadi isi di antararaw_string_literal_delimiter
awal dan akhir. - Dalam kasus
multi_line_raw_string_literal
whitespace* new_line
awal dannew_line whitespace*
akhir bukan bagian dari nilai string. Namun, bagianwhitespace*
akhir sebelum terminalraw_string_literal_delimiter
dianggap sebagai 'spasi indentasi' dan akan memengaruhi bagaimana garis lain ditafsirkan. - Untuk mendapatkan nilai akhir, urutan
(raw_content | new_line)*
ditelusuri dan berikut ini dilakukan:- Jika
new_line
, maka konten darinew_line
ditambahkan ke nilai string akhir. - Jika bukan
raw_content
'kosong' (yaitunot_new_line+
berisi karakter non-whitespace
):- 'spasi kosong indentasi' harus merupakan awalan dari
raw_content
. Jika tidak, itu dianggap kesalahan. - 'Ruang kosong untuk indentasi' dihilangkan dari awal elemen
raw_content
dan sisanya ditambahkan ke nilai string akhir.
- 'spasi kosong indentasi' harus merupakan awalan dari
- Jika
raw_content
'kosong' (yaitunot_new_line+
sepenuhnyawhitespace
):- 'Spasi kosong indentasi' harus merupakan penyusun awal dari
raw_content
atauraw_content
harus merupakan penyusun awal dari 'spasi kosong indentasi'. Jika tidak, itu dianggap kesalahan. - sebanyak mungkin 'spasi kosong indentasi' diambil dari bagian awal
raw_content
dan sisa tersebut ditambahkan ke nilai akhir string.
- 'Spasi kosong indentasi' harus merupakan penyusun awal dari
- Jika
Klarifikasi:
single_line_raw_string_literal
tidak mampu mewakili string dengan nilainew_line
di dalamnya.single_line_raw_string_literal
tidak berpartisipasi dalam pemangkasan 'spasi kosong indentasi'. Nilainya selalu merupakan karakter yang persis antara penanda awal dan akhir.Karena
multi_line_raw_string_literal
mengabaikannew_line
akhir dari baris konten terakhir, berikut ini mewakili string tanpanew_line
awal dan tanpa pengakhirannew_line
.
var v1 = """
This is the entire content of the string.
""";
Ini mempertahankan simetri dengan bagaimana new_line
awal diabaikan, dan juga menyediakan cara yang seragam untuk memastikan 'spasi indentasi' selalu dapat disesuaikan. Untuk mewakili string dengan terminal new_line
baris tambahan harus disediakan seperti:
var v1 = """
This string ends with a new line.
""";
single_line_raw_string_literal
tidak dapat mewakili nilai string yang dimulai atau diakhir dengan tanda kutip ("
) meskipun augmentasi ke proposal ini disediakan di bagianDrawbacks
yang menunjukkan bagaimana hal itu dapat didukung.multi_line_raw_string_literal
dimulai dengan mengikutiwhitespace* new_line
setelahraw_string_literal_delimiter
. Konten ini setelah pemisah sepenuhnya diabaikan dan tidak digunakan dengan cara apa pun saat menentukan nilai string. Ini memungkinkan mekanisme untuk menentukanraw_string_literal
yang kontennya dimulai dengan karakter"
itu sendiri. Misalnya:
var v1 = """
"The content of this string starts with a quote
""";
-
raw_string_literal
juga dapat mewakili konten yang diakhir dengan tanda kutip ("
). Ini didukung karena pemisah penutup harus berada di baris tersendiri. Misalnya:
var v1 = """
"The content of this string starts and ends with a quote"
""";
var v1 = """
""The content of this string starts and ends with two quotes""
""";
- Persyaratan bahwa '
raw_content
kosong' harus menjadi awalan dari 'spasi kosong indentasi' atau 'spasi kosong indentasi' harus menjadi awalannya, membantu memastikan bahwa skenario yang membingungkan dengan spasi kosong campuran tidak terjadi, terutama karena tidak jelas apa yang harus dilakukan dengan baris tersebut. Misalnya, kasus berikut ilegal:
var v1 = """
Start
<tab>
End
""";
Di sini spasi kosong 'indentasi' adalah sembilan karakter spasi, tetapi 'kosong'
raw_content
tidak dimulai dengan awalan itu. Tidak ada jawaban yang jelas sama sekali mengenai bagaimana garis<tab>
itu harus diperlakukan. Haruskah diabaikan? Haruskah sama dengan.........<tab>
? Dengan demikian, menjadikannya ilegal tampaknya merupakan cara paling jelas untuk menghindari kebingungan.Namun, kasus berikut legal dan mewakili string yang sama:
var v1 = """
Start
<four spaces>
End
""";
var v1 = """
Start
<nine spaces>
End
""";
Dalam kedua kasus ini, 'spasi kosong indentasi' akan menjadi sembilan spasi. Dan dalam kedua kasus, kita akan menghapus sebanyak mungkin prefiks itu, sehingga raw_content
menjadi kosong dalam setiap kasus (tidak termasuk setiap new_line
). Ini memungkinkan pengguna untuk tidak perlu melihat dan berpotensi resah tentang spasi kosong pada baris ini ketika mereka menyalin/menempelkan atau mengedit baris ini.
- Dalam hal ini, meskipun:
var v1 = """
Start
<ten spaces>
End
""";
'spasi kosong indentasi' masih akan menjadi sembilan spasi. Di sini, kami akan menghapus sebanyak mungkin 'spasi kosong indentasi', dan 'raw_content
kosong' akan menambah satu spasi ke dalam konten akhir. Ini memungkinkan situasi di mana konten memang membutuhkan spasi kosong pada baris-baris tersebut yang harus dipertahankan.
- Berikut ini secara teknis tidak legal:
var v1 = """
""";
Ini karena awal string mentah harus memiliki new_line
(memilikinya), tetapi ujungnya harus memiliki new_line
juga (tidak memilikinya).
raw_string_literal
hukum minimal adalah:
var v1 = """
""";
Namun, string ini jelas tidak memikat karena setara dengan ""
.
Contoh indentasi
Algoritma 'spasi kosong indentasi' dapat divisualisasikan pada beberapa input sebagai berikut. Contoh berikut menggunakan karakter bilah vertikal |
untuk mengilustrasikan kolom pertama dalam string mentah yang dihasilkan:
Contoh 1 - Kasus standar
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
ditafsirkan sebagai
var xml = """
|<element attr="content">
| <body>
| </body>
|</element>
""";
Contoh 2 - Akhiri pemisah pada baris yang sama dengan konten.
var xml = """
<element attr="content">
<body>
</body>
</element>""";
Ini ilegal. Baris konten terakhir harus diakhir dengan new_line
.
Contoh 3 - Pembatas akhir sebelum pembatas awal
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
ditafsirkan sebagai
var xml = """
| <element attr="content">
| <body>
| </body>
| </element>
""";
Contoh 4 - Pembatas akhir setelah pembatas awal
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
Ini ilegal. Baris konten harus dimulai dengan 'spasi kosong indentasi'
Contoh 5 - Baris kosong kosong
var xml = """
<element attr="content">
<body>
</body>
</element>
""";
ditafsirkan sebagai
var xml = """
|<element attr="content">
| <body>
| </body>
|
|</element>
""";
Contoh 6 - Garis kosong dengan spasi kosong lebih sedikit daripada awalan (titik mewakili spasi)
var xml = """
<element attr="content">
<body>
</body>
....
</element>
""";
ditafsirkan sebagai
var xml = """
|<element attr="content">
| <body>
| </body>
|
|</element>
""";
Contoh 7 - Baris kosong dengan spasi kosong lebih banyak daripada awalan (titik mewakili spasi)
var xml = """
<element attr="content">
<body>
</body>
..............
</element>
""";
ditafsirkan sebagai
var xml = """
|<element attr="content">
| <body>
| </body>
|....
|</element>
""";
Desain terperinci (kasus interpolasi)
Interpolasi dalam string terinterpolasi normal (misalnya $"..."
) saat ini didukung melalui penggunaan karakter {
untuk memulai interpolation
dan penggunaan sekauensi pelolosan {{
untuk memasukkan karakter kurung kurawal terbuka sesungguhnya. Menggunakan mekanisme yang sama ini akan melanggar tujuan '1' dan '2' dari proposal ini. Bahasa yang memiliki {
sebagai karakter inti (contohnya adalah JavaScript, JSON, Regex, dan bahkan C#) sekarang perlu melarikan diri, membatalkan tujuan literal string mentah.
Untuk mendukung interpolasi, kami memperkenalkan interpolasi ini dengan cara yang berbeda dari string interpolasi $"
yang normal. Secara khusus, interpolated_raw_string_literal
akan dimulai dengan beberapa karakter $
. Jumlah karakter ini menunjukkan berapa banyak karakter {
(dan }
) yang diperlukan dalam konten literal untuk membatasi interpolation
. Yang penting, terus tidak ada mekanisme pelepasan untuk kurung kurawal. Sebaliknya, seperti halnya dengan tanda kutip ("
) string literal itu sendiri selalu dapat memastikan bahwa ia menentukan pemisah untuk interpolasi yang pasti tidak akan berbenturan dengan konten lain dari string tersebut. Misalnya JSON literal yang berisi lubang interpolasi dapat ditulis seperti:
var v1 = $$"""
{
"orders":
[
{ "number": {{order_number}} }
]
}
"""
Di sini, {{...}}
cocok dengan jumlah dua kurung kurawal yang diperlukan yang ditentukan oleh prefiks pemisah $$
. Dalam kasus satu $
yang berarti interpolasi ditentukan sama seperti {...}
seperti dalam literal string interpolasi normal. Pentingnya, ini berarti bahwa literal yang diinterpolasi dengan karakter N
$
dapat memiliki urutan kurung kurawal 2*N-1
(dari jenis yang sama berurutan). Kurung kurawal N
terakhir akan memulai (atau mengakhiri) interpolasi, dan kurung kurawal N-1
yang tersisa hanya akan menjadi konten. Misalnya:
var v1 = $$"""X{{{1+1}}}Z""";
Dalam hal ini, kurung kurawal dalam {{
dan }}
adalah milik interpolasi, sedangkan kurung kurawal luar hanya sebagai konten. Jadi string di atas setara dengan konten X{2}Z
. Memiliki kurung kurawal 2*N
(atau lebih) merupakan kesalahan yang selalu terjadi. Untuk memiliki urutan kurung kurawal yang lebih panjang sebagai konten, jumlah karakter $
harus ditingkatkan.
Literal string mentah terinterpolasi didefinisikan sebagai:
interpolated_raw_string_literal
: single_line_interpolated_raw_string_literal
| multi_line_interpolated_raw_string_literal
;
interpolated_raw_string_start
: $
| $$
| $$$
| etc.
;
interpolated_raw_string_literal_delimiter
: interpolated_raw_string_start raw_string_literal_delimiter
;
single_line_interpolated_raw_string_literal
: interpolated_raw_string_literal_delimiter interpolated_raw_content raw_string_literal_delimiter
;
multi_line_interpolated_raw_string_literal
: interpolated_raw_string_literal_delimiter whitespace* new_line (interpolated_raw_content | new_line)* new_line whitespace* raw_string_literal_delimiter
;
interpolated_raw_content
: (not_new_line | raw_interpolation)+
;
raw_interpolation
: raw_interpolation_start interpolation raw_interpolation_end
;
raw_interpolation_start
: {
| {{
| {{{
| etc.
;
raw_interpolation_end
: }
| }}
| }}}
| etc.
;
Di atas mirip dengan definisi raw_string_literal
tetapi dengan beberapa perbedaan penting.
interpolated_raw_string_literal
harus ditafsirkan sebagai:
- Dimulai dengan setidaknya satu tanda dolar (tetapi tidak ada batas atas) dan kemudian tiga tanda kutip (juga tanpa batas atas).
- Kemudian dilanjutkan dengan konten pada baris yang sama dengan tanda kutip awal. Isi pada baris yang sama dapat kosong, atau tidak kosong. 'blank' identik dengan 'sepenuhnya spasi kosong'.
- Jika konten pada baris yang sama tidak kosong, tidak ada konten lebih lanjut yang dapat diikuti. Dengan kata lain, literal harus diakhiri dengan jumlah tanda kutip yang sama pada baris yang sama.
- Jika konten pada baris yang sama kosong, maka literal dapat dilanjutkan dengan
new_line
dan dilanjutkan dengan beberapa baris konten berikutnya dannew_line
.- Baris konten adalah teks apa pun kecuali
new_line
. - Baris konten dapat berisi kemunculan beberapa
raw_interpolation
pada posisi apa pun.raw_interpolation
harus dimulai dengan jumlah kurung kurawal terbuka yang sama ({
) seperti jumlah tanda dolar di awal literal. - Jika 'spasi indentasi kosong' tidak kosong,
raw_interpolation
tidak dapat langsung mengikutinew_line
. -
raw_interpolation
akan mengikuti aturan normal yang ditentukan pada ยง12.8.3. Setiapraw_interpolation
harus berakhir dengan jumlah kurung kurawal tutup (}
) yang sama dengan jumlah tanda dolar dan kurung kurawal buka. - Setiap
interpolation
itu sendiri dapat berisi baris baru dengan cara yang sama sepertiinterpolation
dalamverbatim_string_literal
normal (@""
). - Kemudian berakhir dengan sebuah
new_line
, beberapa angka (mungkin nol)whitespace
, dan jumlah tanda kutip yang sama dengan yang dimulai oleh literal.
- Baris konten adalah teks apa pun kecuali
Komputasi nilai string yang diinterpolasi mengikuti aturan yang sama dengan raw_string_literal
yang biasa, kecuali sudah diperbarui untuk memproses baris yang mengandung raw_interpolation
. Membangun nilai string terjadi dengan cara yang sama, hanya dengan lubang interpolasi diganti dengan nilai apa pun yang dihasilkan ekspresi tersebut pada runtime. Jika interpolated_raw_string_literal
dikonversi ke FormattableString
maka nilai interpolasi diteruskan dalam urutan masing-masing ke array arguments
ke FormattableString.Create
. Konten interpolated_raw_string_literal
lainnya setelah spasi kosong indentasi dihilangkan dari semua baris akan digunakan untuk membuat string format
yang diteruskan ke FormattableString.Create
, kecuali dengan konten {N}
yang diberi nomor sesuai di setiap lokasi di mana raw_interpolation
terjadi (atau {N,constant}
jika interpolation
-nya berbentuk expression ',' constant_expression
).
Ada ambiguitas dalam spesifikasi di atas. Khususnya ketika bagian {
dalam teks dan {
dari interpolasi berdekatan. Misalnya:
var v1 = $$"""
{{{order_number}}}
"""
Ini dapat ditafsirkan sebagai: {{ {order_number } }}
atau { {{order_number}} }
. Namun, karena yang pertama ilegal (tidak ada ekspresi C# yang dapat dimulai dengan {
) tidak ada gunanya untuk menafsirkan cara itu. Jadi kita menafsirkan dengan cara yang terakhir, di mana kurung kurawal {
dan }
terdahulu membentuk interpolasi, dan yang terluar membentuk teks. Di masa depan, hal ini mungkin menjadi masalah kalau bahasa tersebut mendukung ekspresi yang dikelilingi oleh kurung kurawal. Namun, dalam hal ini, rekomendasinya adalah menulis kasus seperti itu: {{({some_new_expression_form})}}
. Di sini, tanda kurung akan membantu membedakan bagian ekspresi dari bagian lain dari literal/interpolasi. Ini telah diutamakan dengan bagaimana ekspresi bersyarat terner perlu dibungkus agar tidak bertentangan dengan penentu pemformatan/perataan interpolasi (misalnya {(x ? y : z)}
).
Kekurangan
Literal string mentah menambahkan lebih banyak kompleksitas ke bahasa. Kita sudah memiliki banyak bentuk literal string untuk berbagai tujuan.
""
string, string @""
, dan string $""
sudah memiliki banyak kekuatan dan fleksibilitas. Tetapi mereka semua tidak memiliki cara untuk menyediakan konten mentah yang tidak pernah perlu melarikan diri.
Aturan di atas tidak mendukung kasus 4.a:
- ...
- Secara opsional, dengan kompleksitas ekstra, kita dapat menyempurnakan ini untuk menyatakan bahwa: Untuk semua string yang tidak berisi
new_line
(tetapi dapat dimulai atau diakhiri dengan karakter kutipan"
), harus dimungkinkan untuk mewakili string literal itu sendiri dalam satu baris.
- Secara opsional, dengan kompleksitas ekstra, kita dapat menyempurnakan ini untuk menyatakan bahwa: Untuk semua string yang tidak berisi
Itu karena kita tidak memiliki sarana untuk mengetahui bahwa kutipan awal atau akhir ("
) harus termasuk dalam konten dan bukan pemisah itu sendiri. Jika ini adalah skenario penting yang ingin kita dukung, kita dapat menambahkan konstruksi '''
paralel yang sejajar dengan bentuk """
. Dengan konstruksi paralel tersebut, string baris tunggal yang dimulai dan diakhir dengan "
dapat ditulis dengan mudah sebagai '''"This string starts and ends with quotes"'''
bersama dengan konstruksi paralel """'This string starts and ends with apostrophes'"""
. Ini mungkin juga diinginkan agar mendukung untuk membantu membedakan karakter kutipan secara visual, yang dapat membantu saat menyematkan bahasa yang umumnya lebih sering menggunakan satu jenis karakter kutipan daripada yang lain.
Alternatif
https://github.com/dotnet/csharplang/discussions/89 mencakup banyak opsi di sini. Alternatifnya banyak, tetapi saya merasa nyasar terlalu jauh ke kompleksitas dan ergonomi yang buruk. Pendekatan ini memilih cara yang sederhana di mana Anda hanya terus memperpanjang tanda kutip awal/akhir hingga tidak ada potensi konflik dengan konten string. Ini juga memungkinkan kode yang Anda tulis terlihat terindentasi dengan baik, sambil tetap menghasilkan literal yang terdedentasi, sesuai dengan yang diperlukan sebagian besar kode.
Salah satu variasi potensial yang paling menarik adalah penggunaan pagar `
(atau ```
) untuk literal string mentah ini. Ini akan memiliki beberapa manfaat:
- Ini akan menghindari semua masalah dengan string yang dimulai atau diakhiri dengan tanda kutip.
- Ini akan terlihat mirip dengan markdown. Meskipun hal itu sendiri berpotensi tidak baik karena pengguna mungkin mengharapkan adanya interpretasi markdown.
- Literal string mentah biasanya hanya perlu dimulai dan diakhiri dengan satu karakter dalam banyak kasus, dan hanya membutuhkan lebih dari satu karakter dalam kasus langka ketika kontennya mengandung tanda back-tick itu sendiri.
- Akan terasa wajar untuk memperluas ini di masa depan dengan
```xml
, sekali lagi mirip dengan markdown. Meskipun, tentu saja, itu juga benar untuk bentuk"""
.
Secara keseluruhan, manfaat bersih di sini tampak kecil. Sesuai dengan riwayat C#, saya pikir "
harus terus menjadi pemisah string literal
, sama seperti untuk @""
dan $""
.
Rapat desain
Masalah terbuka untuk didiskusikan Masalah yang telah diselesaikan:
- [x] haruskah kita memiliki formulir satu baris? Secara teknis kita bisa melakukannya tanpa itu. Tetapi itu berarti string sederhana yang tidak berisi baris baru akan selalu memakan waktu setidaknya tiga baris. Saya pikir kita harus Sangat berat untuk memaksa konstruksi garis tunggal menjadi tiga baris hanya untuk menghindari melarikan diri.
Keputusan desain: Ya, kita akan memiliki formulir satu baris.
- [x] haruskah kita mengharuskan multiline harus mulai dengan baris baru? Kurasa kita harus. Ini juga memberi kita kemampuan untuk mendukung hal-hal seperti
"""xml
di masa depan.
Keputusan desain: Ya, kami akan mengharuskan multibaris harus dimulai dengan baris baru
- [x] haruskah proses dedenting otomatis dilakukan sama sekali? Kurasa kita harus. Itu membuat kode terlihat jauh lebih menyenangkan.
Keputusan desain: Ya, dedenting otomatis akan dilakukan.
- [x] haruskah kita membatasi spasi kosong umum dari mencampur jenis spasi kosong? Saya tidak berpikir kita harus. Memang, ada strategi indentasi umum yang disebut "tab untuk indentasi, spasi untuk penyelarasan". Wajar menggunakan ini untuk menyelaraskan pemisah akhir dengan pemisah awal dalam kasus di mana pemisah mulai tidak berada pada perhentian tab.
Keputusan desain: Kami tidak akan memiliki batasan untuk mencampur spasi kosong.
- [x] haruskah kita menggunakan sesuatu yang lain untuk pagar?
`
akan cocok dengan sintaks markdown, dan berarti kami tidak perlu selalu memulai string ini dengan tiga tanda kutip. Untuk kasus umum, satu saja sudah cukup.
Keputusan desain: Kami akan menggunakan """
- [x] haruskah kita memiliki persyaratan bahwa pemisah memiliki lebih banyak tanda kutip daripada urutan kutipan terpanjang dalam nilai string? Secara teknis itu tidak diperlukan. misalnya:
var v = """
contents"""""
"""
Ini adalah string dengan """
sebagai pemisah. Beberapa anggota komunitas telah menyatakan bahwa ini membingungkan dan kita harus memastikan dalam kasus seperti ini bahwa pemisah selalu memiliki lebih banyak karakter. Itu kemudian akan menjadi:
var v = """"""
contents"""""
""""""
Keputusan desain: Ya, pemisah harus lebih panjang dari urutan tanda kutip dalam string itu sendiri.
C# feature specifications