Interpolacja ciągów przy użyciu polecenia $

Znak $ identyfikuje literał ciągu jako ciąg interpolowany. Ciąg interpolowany to literał ciągu, który może zawierać wyrażenia interpolacji. Gdy ciąg interpolowany jest rozpoznawany jako ciąg wynikowy, elementy z wyrażeniami interpolacji są zastępowane przez reprezentacje ciągów wyników wyrażenia.

Interpolacja ciągów zapewnia bardziej czytelną, wygodną składnię do formatowania ciągów. Łatwiej jest odczytać niż formatowanie złożone ciągów. W poniższym przykładzie użyto obu funkcji do utworzenia tych samych danych wyjściowych:

var name = "Mark";
var date = DateTime.Now;

// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Both calls produce the same output that is similar to:
// Hello, Mark! Today is Wednesday, it's 19:40 now.

Począwszy od języka C# 10, można użyć ciągu interpolowanego, aby zainicjować ciąg stały . Można to zrobić tylko wtedy, gdy wszystkie wyrażenia interpolacji w ciągu interpolowanym są również ciągami stałymi.

Struktura ciągu interpolowanego

Aby zidentyfikować literał ciągu jako ciąg interpolowany, dodaj go do symbolu $ . Nie można mieć żadnego odstępu między znakiem $ i " , który uruchamia literał ciągu.

Struktura elementu z wyrażeniem interpolacji jest następująca:

{<interpolationExpression>[,<alignment>][:<formatString>]}

Elementy w nawiasach kwadratowych są opcjonalne. W poniższej tabeli opisano każdy element:

Element opis
interpolationExpression Wyrażenie, które generuje wynik do sformatowania. Reprezentacja ciągu to nullString.Empty.
alignment Wyrażenie stałe, którego wartość definiuje minimalną liczbę znaków w ciągu reprezentującym wynik wyrażenia. Jeśli jest dodatnia, reprezentacja ciągu jest wyrównana do prawej; jeśli jest ujemna, jest wyrównana do lewej. Aby uzyskać więcej informacji, zobacz sekcję Składnik wyrównania artykułu Formatowanie złożone.
formatString Ciąg formatu obsługiwany przez typ wyniku wyrażenia. Aby uzyskać więcej informacji, zobacz sekcję Format składnika ciągu w artykule Dotyczącym formatowania złożonego.

W poniższym przykładzie użyto opcjonalnych składników formatowania opisanych powyżej:

Console.WriteLine($"|{"Left",-7}|{"Right",7}|");

const int FieldWidthRightAligned = 20;
Console.WriteLine($"{Math.PI,FieldWidthRightAligned} - default formatting of the pi number");
Console.WriteLine($"{Math.PI,FieldWidthRightAligned:F3} - display only three decimal digits of the pi number");
// Output is:
// |Left   |  Right|
//     3.14159265358979 - default formatting of the pi number
//                3.142 - display only three decimal digits of the pi number

Począwszy od języka C# 11, można użyć nowych wierszy w wyrażeniu interpolacji, aby kod wyrażenia był bardziej czytelny. W poniższym przykładzie pokazano, jak nowe wiersze mogą poprawić czytelność wyrażenia obejmującego dopasowywanie wzorca:

string message = $"The usage policy for {safetyScore} is {
    safetyScore switch
    {
        > 90 => "Unlimited usage",
        > 80 => "General usage, with daily safety check",
        > 70 => "Issues must be addressed within 1 week",
        > 50 => "Issues must be addressed within 1 day",
        _ => "Issues must be addressed before continued use",
    }
    }";

Literały nieprzetworzonych ciągów interpolowanych

Począwszy od języka C# 11, można użyć interpolowanego nieprzetworzonego literału ciągu, jak pokazano w poniższym przykładzie:

int X = 2;
int Y = 3;

var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y):F3} from the origin""";

Console.WriteLine(pointMessage);
// Output is:
// The point "2, 3" is 3.606 from the origin

Aby osadzić { znaki i } w ciągu wynikowym, uruchom interpolowany nieprzetworzony literał ciągu z wieloma $ znakami. W takim przypadku każda sekwencja { znaków lub } jest krótsza niż liczba $ znaków osadzonych w ciągu wynikowym. Aby ująć dowolne wyrażenie interpolacji w tym ciągu, należy użyć tej samej liczby nawiasów klamrowych co liczba $ znaków, jak pokazano w poniższym przykładzie:

int X = 2;
int Y = 3;

var pointMessage = $$"""{The point {{{X}}, {{Y}}} is {{Math.Sqrt(X * X + Y * Y):F3}} from the origin}""";
Console.WriteLine(pointMessage);
// Output is:
// {The point {2, 3} is 3.606 from the origin}

W poprzednim przykładzie literał nieprzetworzonego ciągu interpolowany zaczyna się od dwóch $ znaków. Dlatego należy umieścić każde wyrażenie interpolacji między podwójnymi nawiasami klamrowymi {{ i }}. Pojedynczy nawias klamrowy jest osadzony w ciągu wynikowym. Jeśli musisz osadzić powtarzające { się znaki lub } w ciągu wynikowym, użyj odpowiednio większej $ liczby znaków, aby wyznaczyć interpolowany nieprzetworzony literał ciągu.

Znaki specjalne

Aby dołączyć nawias klamrowy "{" lub "}", w tekście utworzonym przez ciąg interpolowany użyj dwóch nawiasów klamrowych, "{{" lub "}}". Aby uzyskać więcej informacji, zobacz sekcję Escaping braces (Ucieczka nawiasów klamrowych) w artykule Dotyczącym formatowania złożonego.

Ponieważ dwukropek (":") ma specjalne znaczenie w elemencie wyrażenia interpolacji, aby użyć operatora warunkowego w wyrażeniu interpolacji, należy ująć to wyrażenie w nawiasy.

W poniższym przykładzie pokazano, jak dołączyć nawias klamrowy do ciągu wynikowego. Pokazano również, jak używać operatora warunkowego:

string name = "Horace";
int age = 34;
Console.WriteLine($"He asked, \"Is your name {name}?\", but didn't wait for a reply :-{{");
Console.WriteLine($"{name} is {age} year{(age == 1 ? "" : "s")} old.");
// Output is:
// He asked, "Is your name Horace?", but didn't wait for a reply :-{
// Horace is 34 years old.

Ciąg interpolowany dosłowny rozpoczyna się od znaków i @$ . Można użyć poleceń $ i @ w dowolnej kolejności: zarówno ciągi interpolowane, jak $@"..." i @$"..." są prawidłowe ciągi dosłowne interpolacji. Aby uzyskać więcej informacji na temat ciągów dosłownych, zobacz artykuły dotyczące ciągów i identyfikatorów dosłownych.

Formatowanie specyficzne dla kultury

Domyślnie ciąg interpolowany używa bieżącej kultury zdefiniowanej CultureInfo.CurrentCulture przez właściwość dla wszystkich operacji formatowania.

Aby rozwiązać ciąg interpolowany do ciągu wynikowego specyficznego dla kultury, użyj String.Create(IFormatProvider, DefaultInterpolatedStringHandler) metody , która jest dostępna począwszy od platformy .NET 6. W poniższym przykładzie pokazano, jak to zrobić:

double speedOfLight = 299792.458;

System.Globalization.CultureInfo.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("nl-NL");
string messageInCurrentCulture = $"The speed of light is {speedOfLight:N3} km/s.";

var specificCulture = System.Globalization.CultureInfo.GetCultureInfo("en-IN");
string messageInSpecificCulture = string.Create(
    specificCulture, $"The speed of light is {speedOfLight:N3} km/s.");

string messageInInvariantCulture = string.Create(
    System.Globalization.CultureInfo.InvariantCulture, $"The speed of light is {speedOfLight:N3} km/s.");

Console.WriteLine($"{System.Globalization.CultureInfo.CurrentCulture,-10} {messageInCurrentCulture}");
Console.WriteLine($"{specificCulture,-10} {messageInSpecificCulture}");
Console.WriteLine($"{"Invariant",-10} {messageInInvariantCulture}");
// Output is:
// nl-NL      The speed of light is 299.792,458 km/s.
// en-IN      The speed of light is 2,99,792.458 km/s.
// Invariant  The speed of light is 299,792.458 km/s.

Na platformie .NET 5 i starszych wersjach platformy .NET użyj niejawnej konwersji ciągu interpolowanego do FormattableString wystąpienia. Następnie możesz użyć metody wystąpienia FormattableString.ToString(IFormatProvider) lub metody statycznej FormattableString.Invariant do utworzenia ciągu wynikowego specyficznego dla kultury. W poniższym przykładzie pokazano, jak to zrobić:

double speedOfLight = 299792.458;
FormattableString message = $"The speed of light is {speedOfLight:N3} km/s.";

var specificCulture = System.Globalization.CultureInfo.GetCultureInfo("en-IN");
string messageInSpecificCulture = message.ToString(specificCulture);
Console.WriteLine(messageInSpecificCulture);
// Output:
// The speed of light is 2,99,792.458 km/s.

string messageInInvariantCulture = FormattableString.Invariant(message);
Console.WriteLine(messageInInvariantCulture);
// Output is:
// The speed of light is 299,792.458 km/s.

Aby uzyskać więcej informacji na temat formatowania niestandardowego, zobacz sekcję Custom formatting with ICustomFormatter (Niestandardowe formatowanie przy użyciu formatu ICustomFormatter ) artykułu Formatting types in .NET (Formatowanie niestandardowe na platformie .NET ).

Inne zasoby

Jeśli dopiero zaczynasz interpolację ciągów, zobacz interaktywny samouczek interpolacji ciągów w języku C# . Możesz również sprawdzić inną interpolację ciągów w samouczku języka C# . W tym samouczku pokazano, jak używać ciągów interpolowanych do tworzenia sformatowanych ciągów.

Kompilacja ciągów interpolowanych

Począwszy od języków C# 10 i .NET 6, kompilator sprawdza, czy ciąg interpolowany jest przypisany do typu spełniającego wzorzec obsługi ciągów interpolowanych. Procedura obsługi ciągów interpolowanych jest typem, który konwertuje ciąg interpolowany na ciąg wynikowy. Gdy ciąg interpolowany ma typ string, jest przetwarzany przez element System.Runtime.CompilerServices.DefaultInterpolatedStringHandler. Aby zapoznać się z przykładem niestandardowej procedury obsługi ciągów interpolowanych, zobacz samouczek Pisanie niestandardowej procedury obsługi interpolacji ciągów. Korzystanie z procedury obsługi ciągów interpolowanych jest zaawansowanym scenariuszem, zwykle wymaganym ze względów wydajności.

Uwaga

Jednym z efektów ubocznych procedur obsługi ciągów interpolowanych jest to, że niestandardowy program obsługi, w tym System.Runtime.CompilerServices.DefaultInterpolatedStringHandler, może nie oceniać wszystkich wyrażeń interpolacji w ciągu interpolowanym we wszystkich warunkach. Oznacza to, że skutki uboczne tych wyrażeń mogą nie wystąpić.

Przed C# 10, jeśli ciąg interpolowany ma typ string, zazwyczaj jest przekształcany w String.Format wywołanie metody. Kompilator może zastąpić String.Format element , String.Concat jeśli przeanalizowane zachowanie będzie równoważne połączeniu.

Jeśli ciąg interpolowany ma typ IFormattable lub FormattableString, kompilator generuje wywołanie FormattableStringFactory.Create metody .

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz sekcję Wyrażenia ciągów interpolowanych specyfikacji języka C# i następujące nowe specyfikacje funkcji:

Zobacz też