Menu

Nội suy chuỗi và String.Format trong C#: định dạng, căn lề, culture

Cách nội suy chuỗi $"..." hoạt động trong C#: biểu thức trong dấu ngoặc nhọn, format specifier như F2, N0, C, D5 và X, căn lề cho bảng, thoát dấu ngoặc nhọn, string.Format và composite formatting, chuỗi nội suy verbatim và raw, và định dạng theo một culture cụ thể.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Nội suy chuỗi (string interpolation) tạo một chuỗi từ văn bản cố định và các biểu thức. Thêm tiền tố $ cho literal, đặt bất kỳ biểu thức C# nào trong dấu ngoặc nhọn, và giá trị của nó sẽ được chuyển thành văn bản rồi chèn vào:

Đầu ra:

Hello, Maya!
3 items at 4.5 = 13.5
Name has 4 letters, upper: MAYA
Free shipping: yes

Nội suy chuỗi có từ C# 6. Trình biên dịch biến nó thành lời gọi string.Format hoặc string.Concat (hoặc, từ C# 10, thành code handler hiệu quả hơn), nên nó không chậm hơn việc tự ghép chuỗi.

Biểu thức điều kiện ở dòng cuối cần dấu ngoặc đơn. Bên trong một chỗ nội suy, dấu hai chấm bắt đầu format specifier, nên {x > 10 ? "yes" : "no"} không có ngoặc đơn sẽ là lỗi biên dịch.

Format specifier

Sau biểu thức, một dấu hai chấm và một chuỗi định dạng quyết định cách giá trị được viết ra. Các chuỗi định dạng này cũng dùng được với ToString("...") và string.Format.

Đầu ra:

1234567.89
1,234,567.89
1,234,568
00042
FF
00ff
1.23E+006
0.813
81.3%
1,234,567.89
007.5
3.1

Các mã chuẩn, mỗi mã có thể kèm theo một số chỉ độ chính xác:

MãTênVí dụKết quả
F hoặc F2Dấu chấm cố định{3.14159:F2}3.14
N hoặc N0Số có dấu phân cách nhóm{1234.56:N0}1,235
CTiền tệ (ký hiệu và mẫu của culture){9.5:C} với en-US$9.50
D5Số nguyên đệm số 0{42:D5}00042
X, xThập lục phân{255:X}FF
E2Ký hiệu khoa học{1234.5:E2}1.23E+003
P1Phần trăm (nhân với 100){0.256:P1} với en-US25.6%
GTổng quát (ngắn nhất){2.50m:G}2.50
RRound-trip (double){0.1:R}0.1

Mẫu tùy chỉnh tạo định dạng từ các ký hiệu giữ chỗ: 0 là chữ số luôn được hiển thị, # là chữ số chỉ hiển thị khi có nghĩa, . là dấu thập phân, , bên trong số bật dấu phân cách nhóm, và % nhân với 100. "0.##" hiển thị tối đa hai chữ số thập phân và bỏ các số 0 thừa ở cuối; "#,##0.00" là định dạng kế toán kinh điển.

Mọi định dạng số đều làm tròn giá trị hiển thị; bản thân biến không thay đổi. Khi một giá trị nằm đúng ở giữa (2.25 hiển thị với một chữ số thập phân), các runtime và kiểu khác nhau có thể làm tròn khác nhau, nên nếu quy tắc này quan trọng, hãy làm tròn tường minh trước bằng Math.Round(value, 1, MidpointRounding.AwayFromZero) rồi mới định dạng.

Ngày giờ trong nội suy chuỗi

Giá trị DateTime nhận chuỗi định dạng ngày theo cùng cách:

Đầu ra:

2026-09-24
24/09/2026 16:05
Thu, Sep 24
Shipped at 16:05 on Thursday
ETA 02:10
2.2 hours

Định dạng tùy chỉnh của TimeSpan yêu cầu các ký tự cố định phải được thoát bằng dấu gạch chéo ngược, mà trong string literal thông thường được viết là \\:. Danh sách đầy đủ các mã ngày (yyyy, MM, HH, tt...) và những lỗi hay mắc với chúng (mm là phút, MM là tháng) có ở trang định dạng DateTime.

Căn lề và đệm khoảng trắng

Dấu phẩy sau biểu thức đặt độ rộng tối thiểu cho trường. Số dương căn phải, số âm căn trái. Kết hợp với định dạng, nó giúp căn thẳng bảng ở dạng văn bản thuần:

Đầu ra:

Item          |  Price| Sold
----------------------------
Espresso      |   2.40|  118
Latte         |   3.60|   64
Hot chocolate |   4.25|    9

Cú pháp là {expression,alignment:format}: căn lề trước, định dạng sau. Giá trị dài hơn độ rộng không bị cắt bớt; nó đẩy phần còn lại của dòng sang bên. PadLeft và PadRight đệm theo cùng cách khi không dùng nội suy.

Thoát dấu ngoặc nhọn

Để in ra dấu ngoặc nhọn, hãy viết gấp đôi: {{ và }}. Điều này thường gặp khi đầu ra là JSON, CSS hoặc code:

Đầu ra:

{ "id": 42, "name": "Ana" }
Set literal: {1, 2, 3}
{42}

Tự ghép JSON như thế này thì được cho một dòng log nhanh; với JSON thật, hãy dùng một thư viện serialize, nó xử lý đúng dấu ngoặc kép và ký tự đặc biệt bên trong name.

string.Format và composite formatting

Trước C# 6, việc định dạng được thực hiện bằng string.Format, nhận các chỗ giữ chỗ được đánh số và một danh sách đối số. Cú pháp composite format này cũng được Console.WriteLine, StringBuilder.AppendFormat và TextWriter.Write chấp nhận:

Đầu ra:

Notebook x4: 14.00
Notebook  |  3.50
echo echo !
Dear Leo, your order #000731 has shipped.

Trong code, hãy ưu tiên nội suy: giá trị nằm ngay tại vị trí nó xuất hiện, nên chỗ giữ chỗ không thể trỏ nhầm đối số. string.Format vẫn là công cụ đúng khi mẫu chuỗi là dữ liệu, như một thông điệp đã dịch được nạp từ tệp tài nguyên. Chỉ số giữ chỗ không có đối số tương ứng ({2} với hai đối số) sẽ ném FormatException lúc chạy.

Culture: kiểm soát dấu phân cách và tiền tệ

Nội suy, ToString và string.Format mặc định đều dùng culture hiện tại của luồng. Trên máy cài đặt tiếng Đức, {1234.5:N2} cho ra 1.234,50; ở Mỹ thì cho ra 1,234.50. Định dạng tiền tệ C dùng ký hiệu của culture. Để chọn culture tường minh, hãy giữ chuỗi nội suy dưới dạng FormattableString rồi định dạng nó với một provider:

Đầu ra:

Total: 1,234.50
Total: 1.234,50
$1,234.50
1.234,50
1234.5,0.75

Hãy dùng culture của người dùng cho văn bản người đọc, và CultureInfo.InvariantCulture cho mọi thứ mà chương trình khác đọc. Một tệp CSV được ghi theo culture hiện tại trên máy tiếng Đức sẽ có dấu phẩy bên trong các số và không đọc được ở nơi khác. Từ .NET 6 trở đi, string.Create(CultureInfo.InvariantCulture, $"...") làm điều tương tự FormattableString.Invariant mà không tạo đối tượng trung gian.

Chuỗi nội suy verbatim và raw

$ kết hợp với @ thành chuỗi nội suy verbatim: dấu gạch chéo ngược được giữ nguyên và chuỗi có thể trải trên nhiều dòng. Từ C# 8 chấp nhận cả hai thứ tự ($@ hoặc @$); C# 6 và 7 bắt buộc $@:

Đầu ra:

C:\Users\ana\Reports\2026\summary.txt
Report for ana
Year: 2026

C# 11 bổ sung chuỗi nội suy raw. Với một $, dấu ngoặc nhọn đánh dấu biểu thức như thường lệ. Với $$, dấu ngoặc nhọn đơn là ký tự thường và biểu thức cần hai dấu ngoặc nhọn, giúp các mẫu JSON và code dễ đọc hơn:

// C# 11 and later
int id = 42;
string name = "Ana";
string json = $$"""
    {
      "id": {{id}},
      "name": "{{name}}"
    }
    """;

C# 11 cũng cho phép xuống dòng bên trong một chỗ nội suy, nên biểu thức dài hoặc biểu thức switch có thể được chia ra nhiều dòng.

Lỗi thường gặp

  • Quên $. "Total: {total}" in nguyên văn cả dấu ngoặc nhọn. Trình biên dịch không cảnh báo.
  • Toán tử ba ngôi không có dấu ngoặc đơn bên trong dấu ngoặc nhọn: dấu hai chấm bị hiểu là dấu phân cách định dạng.
  • Định dạng đầu ra cho máy đọc theo culture hiện tại. Dấu phẩy thập phân làm hỏng CSV, JSON và SQL. Hãy dùng invariant culture.
  • Dùng ToString() không kèm định dạng cho tiền. 2.5m in ra 2.5, không phải 2.50. Hãy dùng F2, N2 hoặc C.
  • Tạo chuỗi lớn bằng nội suy trong vòng lặp. Mỗi lần lặp tạo một chuỗi mới; hãy dùng StringBuilder hoặc string.Join.

Câu hỏi thường gặp

Nội suy chuỗi trong C# là gì?

Là một string literal có tiền tố $, trong đó các biểu thức nằm trong dấu ngoặc nhọn được tính và chèn vào: $"Total: {price * qty}". Tính năng này có từ C# 6 và thay thế hầu hết các trường hợp dùng string.Format và nối chuỗi bằng +. Mọi biểu thức đều dùng được trong dấu ngoặc nhọn, kể cả lời gọi phương thức và truy cập thuộc tính.

Làm sao định dạng số với 2 chữ số thập phân trong C#?

Thêm format specifier sau dấu hai chấm: $"{price:F2}" in ra 2 chữ số sau dấu thập phân, còn $"{price:N2}" làm điều tương tự kèm dấu phân cách hàng nghìn. Ngoài nội suy, các mã này cũng dùng được với price.ToString("F2"). Cả hai đều làm tròn giá trị để hiển thị mà không thay đổi giá trị gốc.

Làm sao thoát dấu ngoặc nhọn trong chuỗi nội suy C#?

Viết gấp đôi: {{ in ra { và }} in ra }. Ví dụ $"{{ \"id\": {id} }}" in ra { "id": 42 }. Với chuỗi nội suy raw của C# 11, bạn có thể bắt đầu literal bằng $$ để dấu ngoặc nhọn đơn là ký tự thường và {{expr}} đánh dấu biểu thức.

string.Format và nội suy chuỗi khác nhau thế nào?

Chúng cho cùng kết quả với cùng các mã định dạng. string.Format("{0} costs {1:F2}", name, price) tham chiếu đối số theo vị trí; $"{name} costs {price:F2}" đặt biểu thức ngay tại chỗ, nên dễ đọc hơn và không thể nhầm thứ tự đối số. string.Format vẫn cần thiết khi chính chuỗi định dạng đến từ tệp tài nguyên hoặc cơ sở dữ liệu.

Vì sao số trong chuỗi nội suy hiển thị dấu phẩy thay vì dấu chấm?

Nội suy định dạng theo culture hiện tại của luồng, và nhiều culture dùng dấu phẩy làm dấu thập phân. Với đầu ra dành cho máy đọc (tệp, JSON, URL), hãy định dạng bằng invariant culture: FormattableString.Invariant($"{value:F2}"), hoặc từ .NET 6 trở đi là string.Create(CultureInfo.InvariantCulture, $"...").

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu