Interpolated strings - IS4Code/Sona GitHub Wiki

Interpolated strings are strings that contain dynamic parts that are expressed directly as embedded expressions. The results of the expressions can be optionally formatted using a special format string.

Syntax

interpolated_string:
 '$"' (string_part | '{{' | '}}' | interpolation)* '"';

verbatim_interpolated_string:
  ('$@"' | '@$"') (verbatim_string_part | '{{' | '}}' | interpolation)* '"';

interpolation:
  '{' expression (',' alignment)? (':' (checked_format | unchecked_format)) '}';

The syntax for interpolated strings is derived from that of regular strings, with a preceding $ character. Inside the string, {expression} is used to embed a dynamically-computed value between the surrounding parts of the string. Literal characters { and } are escaped by doubling them (even in a verbatim string).

The , and : characters in an interpolation are followed by the alignment and format specification. Other occurrences of these characters in the interpolation are invalid and must be wrapped in parentheses. All other pieces of syntax are valid in an interpolation, even other strings.

The interpolation expression may be followed by alignment, consisting of a single integer indicating the number of spaces to fit in (positive if spaces are added to the right, negative if to the left).

The last component, after :, is the format specification. It takes one of the following forms, in this priority:

  • A character literal, denoting a single-character standard .NET-style format. The character must be a letter. Both this and the following kind of format is not type-checked, and uses the value's implementation of ToString.

  • A string or a verbatim string, denoting a custom .NET-style format, or a standard format with 2 or more characters. The string must not be a single letter.

  • An F#-style format, as a sequence of the form [flags][width][.precision]type. The type is indicated by a single letter and constrains the type of the interpolated value. As the other components are optional, any single letter matches this form. Unlike in F#, % is not used to indicate this form (and has no special meaning within interpolated strings altogether).

  • A standard or custom numeric format, constraining the type of the interpolation to a number. The format supports escape sequences using \ and treats spaces, tabs, +, -, _, and anything enclosed in ' as literal. The format is further restricted to avoid potential sources of errors or confusion with other formats:

    • The precision specifier in the standard format is restricted to a maximum of 99. (G100 is invalid.)
    • In the custom format, the integral part (before the decimal point) must contain at least one 0 or # specifier. (.0 is invalid.)
    • The , specifier, when used to separate groups, must be surrounded on both sides by 0 or #. (0,,0.0 is invalid.) When used as a scaling specifier, it must not be interrupted by any other character, and must be placed immediately to the left of the decimal point, or where the decimal point would be. (0, ,.0 or 0.0,,, is invalid.)
    • The decimal point character (.) may appear unescaped at most once, and must be immediately followed by a 0 or # character. (0.0.0 or 0. is invalid.)
    • The 0 specifiers must be all clustered around the decimal point with respect to the # specifiers. (0# or #.#0 is invalid.)
    • The e or E custom specifier may not be placed before the decimal point and may appear only once. (0e0.0 is invalid.)
    • The % or character may appear unescaped at most once, and must be located at the edge of a section. (0%.0 is invalid.)
    • The number of ;-separated sections is limited to 3. The ; character may not appear unescaped anywhere else in the format. (0;0;0;0 is invalid.)
    • Literal characters and escapes are allowed in all meaningful positions (i.e. not between , and . or inside e/E).
  • A custom date, time, or time span format, constraining the type of the interpolation based on the specifiers occurring in the format:

    • h, m, s, f, or F require the value to have the trait time or timespan.
    • y or M require the value to have the trait date or datespan.
    • d requires the value to have the trait date or timespan.
    • g or / require the value to have the trait date.
    • H, t, or : require the value to have the trait time.
    • z or K require the value to have the traits date and time.
    • The instant and span traits must not mix as the only way for a type to be valid, for example a type is never required to have both the date and timespan trait.
    • In case of a combination of these specifier groups, the traits are determined by a logical conjunction, for example yh requires time or timespan and date or datespan, which is further restricted by the previous rule to time and date or timespan and datespan.

    The format supports same literal/escape sequences as above. Likewise, there are restrictions on the syntax itself:

    • At least one letter specifier (i.e. not : or /) must be present.
    • With the exception of non-letter specifiers, a specifier may not appear multiple times, including variants that effectively expose the same value (up to padding/truncation). This depends on the accepted type of the value, for example dd and dddd are considered the same specifier for timespan types, but different for date types.
    • A specifier may not consist of more characters than what is necessary for its effect. This also depends on the type, for example ddddd is valid for timespan types, but not for date. Note that % may be used to treat the following character as a singular specifier, so both %ddddd and dddd%d are valid formats for date types (but not timespan due to repetition).
    • Only one of the h and H specifiers may be used.
    • Only one of the f and F specifiers may be used.
    • The format must have distinct sections for date (y, M, d, /), time (h, H, m, s, f, F, t, :), time zone (z, K), and era (g). A particular section type may not occur multiple times, therefore all specifiers pertaining to the same section must appear together.
    • The : specifier is allowed only between other time specifiers.
    • The / specifier is allowed only between other date specifiers.
    • The % character must not appear at the end of the format.
    • Escapes are allowed in all positions except when immediately following a non-escaped % character.
⚠️ **GitHub.com Fallback** ⚠️