Nội suy chuỗi so với String.Format


113

Có sự khác biệt về hiệu suất đáng chú ý giữa việc sử dụng nội suy chuỗi không:

myString += $"{x:x2}";

so với String.Format ()?

myString += String.Format("{0:x2}", x);

Tôi chỉ hỏi vì Resharper đang nhắc bản sửa lỗi và tôi đã bị lừa trước đây.


4
Tại sao không thử cả hai và xem bạn có nhận thấy sự khác biệt không?
Blorgbeard ra mắt vào

57
@Blorgbeard Thành thật mà nói, tôi lười biếng. Và tôi nghĩ rằng sẽ mất ít thời gian hơn nếu một trong số các bạn là nam / nữ đứng đắn biết câu trả lời.
Krythic

26
Tôi thích làm thế nào khi lần đầu tiên tôi hỏi câu hỏi này, nó đã chìm vào quên lãng và bây giờ, hai năm sau, nó đã lên tới +21.
Krythic

46
Nghiêm túc. Làm thế nào ai có thể nghi ngờ sự hữu ích của câu hỏi này? Bạn có thể tưởng tượng sự lãng phí tổng số giờ làm việc của con người không, nếu mọi người hỏi câu hỏi này phải 'tự mình thử xem?' Ngay cả khi chỉ mất 5 phút, hãy nhân lên với hơn 10.000 nhà phát triển đã xem câu hỏi này cho đến nay. Và sau đó bạn sẽ làm gì khi đồng nghiệp nghi ngờ kết quả của bạn? Làm lại tất cả? Hoặc có thể chỉ cần giới thiệu họ đến bài đăng SO này. Đó là những gì nó ở đó để làm.
BTownTKD

8
@BTownTKD Đó là hành vi Stackoverflow điển hình dành cho bạn. Nếu bất kỳ ai sử dụng trang web cho mục đích dự định, họ sẽ bị xa lánh ngay lập tức. Đây cũng là một trong những lý do tại sao tôi nghĩ chúng ta nên được phép cấm tài khoản chung. Nhiều người chỉ đơn giản là không xứng đáng có mặt trên trang web này.
Krythic

Câu trả lời:


72

Đáng chú ý là tương đối. Tuy nhiên: nội suy chuỗi được chuyển thành string.Format()lúc biên dịch nên chúng sẽ có cùng kết quả.

Tuy nhiên, có sự khác biệt nhỏ: như chúng ta có thể biết từ câu hỏi này , việc nối chuỗi trong trình định dạng sẽ dẫn đến một string.Concat()lệnh gọi bổ sung .


4
Trên thực tế, nội suy chuỗi có thể biên dịch thành nối chuỗi trong một số trường hợp (ví dụ: khi a intđược sử dụng). var a = "hello"; var b = $"{a} world";biên dịch để nối chuỗi. var a = "hello"; var b = $"{a} world {1}";biên dịch sang định dạng chuỗi.
Omar Muscatello

5

nội suy chuỗi được chuyển thành string.Format () tại thời gian biên dịch.

Cũng trong string.Format, bạn có thể chỉ định một số đầu ra cho một đối số và các định dạng đầu ra khác nhau cho một đối số. Nhưng tôi đoán là nội suy chuỗi dễ đọc hơn. Vì vậy, nó tùy thuộc vào bạn.

a = string.Format("Due date is {0:M/d/yy} at {0:h:mm}", someComplexObject.someObject.someProperty);

b = $"Due date is {someComplexObject.someObject.someProperty:M/d/yy} at {someComplexObject.someObject.someProperty:h:mm}";

Có một số kết quả kiểm tra hiệu suất https://koukia.ca/string-interpolation-vs-string-format-string-concat-and-string-builder-performance-benchmarks-c1dad38032a


2
nội suy chuỗi chỉ đôi khi được chuyển thành String::Format. và đôi khi thành String::Concat. Và kiểm tra hiệu suất trên trang đó không thực sự có ý nghĩa: số lượng đối số bạn chuyển cho mỗi phương thức đó là phụ thuộc. concat không phải lúc nào cũng nhanh nhất, stringbuilder không phải lúc nào cũng chậm nhất.
Matthias Burger

3

Câu hỏi là về hiệu suất, tuy nhiên tiêu đề chỉ nói "vs", vì vậy tôi cảm thấy phải thêm một vài điểm nữa, một số trong số đó là ý kiến.

  • Bản địa hóa

    • Nội suy chuỗi không thể được bản địa hóa do tính chất mã nội tuyến của nó. Trước khi bản địa hóa nó đã được chuyển thành string.Format. Tuy nhiên, có công cụ cho điều đó (ví dụ ReSharper).
  • Khả năng bảo trì (ý kiến ​​của tôi)

    • string.Formatdễ đọc hơn nhiều, vì nó tập trung vào câu mà tôi muốn diễn đạt, chẳng hạn như khi xây dựng một thông báo lỗi hay và có ý nghĩa. Việc sử dụng các {N}trình giữ chỗ giúp tôi linh hoạt hơn và dễ dàng sửa đổi nó hơn sau này.
    • Ngoài ra, từ định dạng nội tuyến trong lồng vào nhau rất dễ đọc nhầm và dễ xóa cùng với biểu thức trong quá trình thay đổi.
    • Khi sử dụng các biểu thức phức tạp và dài, nội suy nhanh chóng thậm chí còn khó đọc và khó bảo trì hơn, vì vậy theo nghĩa này, nó không mở rộng quy mô tốt khi mã đang phát triển và phức tạp hơn. string.Formatít bị điều này hơn nhiều.
    • Vào cuối ngày, tất cả là về sự tách biệt của những mối quan tâm: Tôi không thích trộn lẫn cách nó nên trình bày với những gì nên trình bày .

Vì vậy, dựa trên những điều này, tôi quyết định gắn bó với string.Formathầu hết các mã của mình. Tuy nhiên, tôi đã chuẩn bị một phương pháp mở rộng để có cách viết mã trôi chảy hơn mà tôi thích hơn nhiều. Triển khai của tiện ích mở rộng là một lớp lót và nó trông đơn giản như thế này khi được sử dụng.

var myErrorMessage = "Value must be less than {0:0.00} for field {1}".FormatWith(maximum, fieldName);

Nội suy là một tính năng tuyệt vời, đừng hiểu sai ý tôi. Nhưng IMO thì nó lại tỏa sáng tốt nhất trong những ngôn ngữ không string.Formatcó tính năng giống, ví dụ như JavaScript.


Cảm ơn bạn đã thêm vào điều này.
Krythic

1
Tôi không đồng ý về khả năng bảo trì; ReSharper được cấp giúp việc so khớp các giá trị được chèn với các chỉ số tương ứng của chúng (và ngược lại) dễ dàng hơn một chút nhưng tôi nghĩ vẫn cần nhiều nhận thức hơn để tìm ra xem {3}là X hay Y, đặc biệt nếu bạn bắt đầu sắp xếp lại định dạng của mình. Ví dụ về Madlibs: $"It was a {adjective} day in {month} when I {didSomething}"vs string.Format("It was a {0} day in {1} when I {2}", adjective, month, didSomething)-> $"I {didSomething} on a {adjective} {month} day"vsstring.Format("I {2} on a {0} {1} day", adjective, month, didSomething)
drzaus

@drzaus Cảm ơn bạn đã chia sẻ suy nghĩ của mình. Bạn có những điểm tốt, tuy nhiên nó chỉ đúng nếu chúng ta chỉ sử dụng các biến cục bộ đơn giản, được đặt tên tốt. Những gì tôi đã thấy khá nhiều lần là các biểu thức phức tạp, các cuộc gọi hàm, bất cứ thứ gì được đưa vào chuỗi nội suy. Với string.Formattôi nghĩ rằng bạn ít bị vấn đề này hơn nhiều. Nhưng dù sao, đây là lý do tại sao tôi nhấn mạnh rằng đó là ý kiến ​​của tôi :)
Zoltán Tamási
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.