To follow-up do mojej oryginalnej odpowiedzi w celu
, aby upewnić się, że jest to zamierzone zachowanie:
Jeśli chodzi o oficjalne źródło, powinniśmy odnosić się do Interpolated Strings z msdn.
Strukturę interpolowana ciąg jest
$ " <text> { <interpolation-expression> <optional-comma-field-width> <optional-colon-format> } <text> ... } "
a każdy pojedynczy interpolacja jest formalnie zdefiniowana w składni
single-interpolation:
interpolation-start
interpolation-start : regular-string-literal
interpolation-start:
expression
expression , expression
Tu liczy, że
optional-colon-format
jest zdefiniowana jako składnia regular-string-literal
=> tj. może zawierać escape-sequence
, zgodnie z paragraph 2.4.4.5 String literals
z C# Language Specification 5.0
- można użyć interpolowana ciąg wszędzie można użyć
string literal
- Aby dołączyć nawias klamrowy (
{
lub }
) w interpolowana ciąg użyć dwóch nawiasów klamrowych, {{
lub }}
= > tj kompilator ucieka dwa nawiasów klamrowych w optional-colon-format
- kompilator skanuje zawarty interpolacji
expressions
jako symetryczne tekstu aż znajdzie przecinek, okrężnicy, albo w pobliżu nawiasem => tj okrężnicy przerwy wyważony tekst jak bliski nawias klamrowy
Żeby było jasne, to wyjaśnia różnicę między $"{{{date}}}"
gdzie date
jest expression
a więc jest tokenized do pierwszego nawias klamrowy kontra $"{{{date:o}}}"
gdzie date
jest znowu expression
i teraz jest to tokenized aż do pierwszego dwukropek, po którym regularny ciąg dosłowne zaczyna i kompilator powraca ucieczce dwa nawiasy klamrowe, itp ...
Istnieje również String Formatting FAQ z MSDN, gdzie ta sprawa był wyraźnie potraktowane.
int i = 42;
string s = String.Format(“{{{0:N}}}”, i); //prints ‘{N}’
Pytanie jest, dlaczego ta ostatnia próba nie powiedzie?Są dwie rzeczy trzeba wiedzieć, aby zrozumieć ten wynik:
Świadcząc formacie specyfikator formatowanie ciąg traktuje te etapy:
Ustal, czy specifier jest dłuższy niż jeden znak: jeśli tak, następnie założyć, że specyfikator jest niestandardowym formatem. Niestandardowy format użyje odpowiednich zamienników dla twojego formatu, ale jeśli nie będzie wiedział, co zrobić z jakimś charakterem, po prostu wypisze go jako literał znaleziony w formacie Ustal, czy pojedynczy znak Specyfikator jest obsługiwany specyfikator (na przykład "N" w przypadku formatowania ). Jeśli tak, sformatuj odpowiednio. Jeśli nie, rzucać ArgumnetException
Podczas próby ustalenia, czy kręcone wspornik powinien być uciekł, nawiasy klamrowe są po prostu traktowane w kolejności, w jakiej są odebrany. W związku z tym {{{
będzie uciec od pierwszych dwóch znaków, a wydrukuje literał {
, a trzeci nawias klamrowy rozpocznie sekcję formatowania . Na tej podstawie w }}}
zostaną usunięte pierwsze dwa nawiasy klamrowe , dlatego literowy }
zostanie zapisany w postaci ciąg formatu, a następnie ostatni nawias klamrowy zostanie przyjęty na , kończąc sekcję formatowania z tymi informacjami, teraz można dowiedzieć się, co dzieje się w naszej sytuacji {{{0:N}}}
. Pierwsze dwa nawiasy klamrowe są unikane, a następnie mamy sekcję formatowania. Jednakże, również wtedy unikamy zamykającego nawiasu klamrowego, przed zamknięciem sekcji formatowania . Dlatego nasza sekcja formatowania jest w rzeczywistości interpretowana jako zawierająca 0:N}
. Teraz formater analizuje specyfikator formatu i widzi N}
dla specyfikatora. Dlatego też, interpretuje to jako format niestandardowy, a ponieważ ani N ani} oznacza niczego dla niestandardowego formatu liczbowego, te znaki są po prostu wypisywane, a nie wartością odnośnej zmiennej.
Pojawia się (chociaż nie znoszę tego mówić), że jest to błąd kompilatora. – DavidG
@DavidG: Może to być błąd kompilatora lub może być błędem w bazowej bibliotece formatowania, ale zgadzam się, że coś tu śmierdzi. To przynajmniej powinno być zbadane. –
Wydaje się, że ma to związek ze sposobem sprawdzania nawiasu zamykającego interpolacji.Z powyższym kodem zewnętrzny nawias zamyka interpolację '{{countdown | ** {** date: o}} **} **', spacja między nawiasami powoduje jej ocenę do wewnętrznego nawiasu '{{countdown | ** {** date: o **} ** _}} '. – Equalsk