使用 $ 的字串內插補點

$ 字元會將字串常值識別為「差補字串」。 插入字串是可能包含「內插補點運算式」的字串常值。 將插入字串解析為結果字串時,會將具有內插補點運算式之項目取代為運算式結果的字串表示。

字串插補提供更易於讀取且更便利的語法來格式化字串。 比字串複合格式更容易於讀取。 下列範例會使用這兩項功能,產生相同的輸出:

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.

從 C# 10 開始,您可以使用差補字串來初始化常數字串。 只有當差補字串內的所有內插補點運算式都是常數字串時,您才能這麼做。

插入字串的結構

若要將字串常值識別為插入字串,請在其前面加上 $ 符號。 字串常值開頭的 $" 之間不能有空白字元。

具有內插補點運算式的項目結構如下所示:

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

在方括號中的元素是選擇性的元素。 下表說明每個元素:

元素 描述
interpolationExpression 產生要格式化之結果的運算式。 null 的字串表示法是 String.Empty
alignment 常數的運算式,其值定義運算式結果的字串表示法的字元數最小值。 如果是正數,則字串表示是靠右對齊;如果是負數,它是靠左對齊。 如需詳細資訊,請參閱複合格式文章中的對齊元件一節。
formatString 運算式結果的類型所支援的格式字串。 如需詳細資訊,請參閱複合格式主題的格式字串元件一節。

下列範例會使用上述的選擇性格式化元件:

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

從 C# 11 開始,您可以在內插補點運算式內使用換行符號,讓運算式的程式碼更容易閱讀。 下列範例顯示換行符號如何改善涉及模式比對的運算式可讀性:

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",
    }
    }";

插入的原始字串常值

從 C# 11 開始,您可以使用插入的原始字串常值,如下列範例所示:

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

若要在結果字串中內嵌 {} 字元,請使用多個 $ 字元啟動插入的原始字串常值。 執行此操作時,任何短於 $ 字元數的 {} 字元序列都會內嵌到結果字串中。 若要在該字串中括住任何內插補點運算式,您必須使用與 $ 字元數相同的大括號數目,如下列範例所示:

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}

在上述範例中,插入的原始字串常值會以兩個 $ 字元開頭。 這就是為什麼您必須將每個內插補點運算式放置在雙大括號 {{}} 之間。 單一大括號會內嵌到結果字串中。 如果您需要將重複的 {} 字元內嵌至結果字串,請使用適當數目的 $ 字元來指定插入的原始字串常值。

特殊字元

若要在插入字串所產生的文字中包含大括弧 "{" 或 "}",請使用雙大括弧 "{{" 或 "}}"。 如需詳細資訊,請參閱複合格式文章中的逸出大括號一節。

因為冒號 (":") 在內插補點運算式項目中具有特殊意義,為了在內插補點運算式中使用條件運算子,請用括號將運算式括在之中。

下列範例顯示如何在結果字串中包含大括號。 它也會示範如何使用條件運算子:

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.

插入的逐字字串會以 $@ 字元開頭。 您可以依任何順序使用 $@$@"..."@$"..." 都是有效的差補逐字字串。 如需逐字字串的詳細資訊,請參閱字串逐字識別碼一文。

特定文化特定的格式

根據預設,插入字串會使用 CultureInfo.CurrentCulture 屬性針對所有格式設定作業所定義的目前文化特性。

若要將差補字串解析為特定文化特性的結果字串,請使用 String.Create(IFormatProvider, DefaultInterpolatedStringHandler) 方法,該方法從 .NET 6 開始提供。 下列範例顯示如何執行該項工作:

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.

在 .NET 5 和舊版 .NET 中,使用差補字串隱含轉換成 FormattableString 執行個體。 然後,您可以使用執行個體 FormattableString.ToString(IFormatProvider) 方法或靜態 FormattableString.Invariant 方法來產生特定文化特性的結果字串。 下列範例顯示如何執行該項工作:

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.

如需自訂格式的詳細資訊,請參閱 .NET 中的格式設定類型文章中的使用 ICustomFormatter 自訂格式一節。

其他資源

如果您是字串插補的新手,請參閱 C# 中的字串插補互動式教學課程。 您也可以在 C# 教學課程中檢查另一個字串插補。 該教學課程會示範如何使用差補字串產生格式化的字串。

內插字串的編譯

從 C# 10 和 .NET 6 開始,編譯器會檢查差補字串是否指派給符合差補字串處理常式模式的型別。 差補字串處理常式是一種型別,可將差補字串轉換成結果字串。 當差補字串具有 string 型別時,會由 System.Runtime.CompilerServices.DefaultInterpolatedStringHandler 處理。 如需自訂差補字串處理常式的範例,請參閱撰寫自訂字串插補處理常式教學課程 (部分機器翻譯)。 使用差補字串處理常式是進階案例,通常出於效能原因而需要。

注意

差補字串處理常式的其中一個副作用是自訂處理常式 (包括 System.Runtime.CompilerServices.DefaultInterpolatedStringHandler) 可能無法在所有情況下,在評估差補字串內的所有內插補點運算式。 這表示這些運算式可能不會發生副作用。

在 C# 10 前,如果差補字串的型別為 string,它通常會轉換成 String.Format 方法呼叫。 如果分析的行為相當於串連,編譯器可以將 String.Format 取代為 String.Concat

如果內插字串的類型為 IFormattableFormattableString,編譯器會產生 FormattableStringFactory.Create 方法的呼叫。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格差補字串運算式一節,以及下列新功能規格:

另請參閱