2009-12-01 35 views
51

Tôi hiểu những lợi ích của StringBuilder.Khi nào sử dụng StringBuilder?

Nhưng nếu tôi muốn nối 2 chuỗi, thì tôi cho rằng tốt hơn (nhanh hơn) để thực hiện nó mà không có StringBuilder. Điều này có đúng không?

Tại thời điểm nào (số chuỗi) nó trở nên tốt hơn để sử dụng StringBuilder?

+1

Tôi tin rằng điều này đã được đề cập trước đó. –

+2

Rất nhiều lần –

+1

Có khả năng trùng lặp: http://stackoverflow.com/questions/529999, http://stackoverflow.com/questions/550702, http://stackoverflow.com/questions/1612797, http: // stackoverflow. com/questions/21078, http://stackoverflow.com/questions/73883, –

Trả lời

57

Tôi nhiệt liệt đề nghị bạn đọc The Sad Tragedy of Micro-Optimization Theater, của Jeff Atwood.

Nó xử lý ghép nối đơn giản so với StringBuilder so với các phương pháp khác.

Bây giờ, nếu bạn muốn xem một số con số và đồ thị, hãy làm theo các liên kết;)

+0

+1 cho _yes_! Thời gian lo lắng về việc này là thời gian không làm điều gì đó thực sự quan trọng. –

+5

Đọc của bạn là sai tuy nhiên: nó không quan trọng trong rất nhiều trường hợp, khi không looping là có liên quan, trong các trường hợp khác tuy nhiên nó có thể quan trọng A LOT – Peter

+0

Tôi đã gỡ bỏ chỉnh sửa, bởi vì nó chỉ là sai thông tin trong một câu trả lời chấp nhận . – Peter

1

Một kết nối đơn lẻ không có giá trị khi sử dụng trình tạo chuỗi. Tôi đã thường sử dụng 5 concatenations như một quy tắc của ngón tay cái.

8

Không thực sự ... bạn nên sử dụng StringBuilder nếu bạn nối các chuỗi lớn hoặc bạn có nhiều kết nối, giống như trong vòng lặp.

+1

Điều đó là sai. Bạn nên sử dụng 'StringBuilder' chỉ khi vòng lặp hoặc kết nối là một vấn đề hiệu suất với các thông số kỹ thuật. –

+0

-1 để khái quát hóa không chính xác. string s = "a" + "b" + "c" + "d"; sử dụng một cấp phát bộ nhớ cho s. Nhìn vào quá tải (9th) cuối cùng cho string.Concat. Đoạn mã trên cơ bản được biên dịch xuống thành chuỗi.Concat ("a", "b", "c", "d") trong MSIL. –

+2

@ Alex: Không phải luôn luôn như vậy sao? ;) Không, nghiêm túc, tôi đã luôn luôn sử dụng StringBuilder cho nối bên trong một vòng lặp ... mặc dù, vòng của tôi tất cả có hơn 1k lặp ... @Binary: Thông thường, cần được biên dịch thành 'string s =" abcd " ', ít nhất đó là điều cuối cùng tôi nghe ... mặc dù, với các biến nó sẽ, rất có thể, Concat. – Bobby

4

Nhưng nếu tôi muốn kết hợp 2 chuỗi, thì tôi cho rằng tốt hơn (nhanh hơn) để thực hiện nó mà không có StringBuilder. Điều này có đúng không?

Có. Nhưng quan trọng hơn, nó là nhiều hơn có thể đọc được để sử dụng vanilla strings trong những trường hợp như vậy. Sử dụng nó trong một vòng lặp, mặt khác, có ý nghĩa và cũng có thể được đọc như nối.

Tôi rất thận trọng với các quy tắc chung cho biết số lượng các kết nối cụ thể dưới dạng ngưỡng. Sử dụng nó trong vòng lặp (và vòng chỉ) có lẽ chỉ là hữu ích, dễ nhớ hơn và có ý nghĩa hơn.

+0

"Tôi sẽ cảnh giác với các quy tắc chung mà trích dẫn một số lượng cụ thể của việc nối như một ngưỡng"

34

Nhưng nếu tôi muốn concatinate 2 chuỗi, sau đó tôi cho rằng đó là tốt hơn (nhanh hơn) để làm nó không có StringBuilder. Điều này có đúng không?

Đó là thực sự chính xác, bạn có thể tìm thấy lý do tại sao chính xác giải thích rất tốt trên:

http://www.yoda.arachsys.com/csharp/stringbuilder.html

tóm tắt: nếu bạn có thể concatinate chuỗi trong một đi như

var result = a + " " + b + " " + c + .. 

bạn tốt hơn nếu không có trình xây dựng chuỗi chỉ cho bản sao được thực hiện (độ dài của chuỗi kết quả được tính toán trước);

Đối structurs như

var result = a; 
result += " "; 
result += b; 
result += " "; 
result += c; 
.. 

đối tượng mới được tạo ra mỗi lần, do đó bạn nên xem xét StringBuilder.

Vào cuối bài viết tóm tắt các quy tắc của ngón tay cái:

Rules of Thumb

Vì vậy, khi bạn nên sử dụng StringBuilder, và khi nào bạn nên sử dụng các toán tử nối chuỗi ?

  • Chắc chắn sử dụng StringBuilder khi bạn đang concatenating trong một vòng lặp không tầm thường - đặc biệt là nếu bạn không biết cho chắc chắn (tại thời gian biên dịch) có bao nhiêu lặp bạn sẽ thực hiện thông qua các vòng lặp. Ví dụ: mỗi lần đọc một tệp là ký tự, hãy tạo một chuỗi khi bạn sử dụng toán tử + = có khả năng tự tử hiệu suất.

  • Chắc chắn sử dụng kết nối toán tử khi bạn có thể (có thể đọc được) chỉ định mọi thứ cần được nối trong một tuyên bố. (Nếu bạn có một loạt các điều cần concatenate, hãy xem xét gọi String.Concat một cách rõ ràng -. Hoặc String.Join nếu bạn cần một delimiter)

  • Đừng ngại để phá vỡ literals lên thành nhiều các bit ghép nối - kết quả sẽ giống nhau. Bạn có thể hỗ trợ khả năng đọc bằng cách chia nhỏ một chữ dài thành nhiều dòng, ví dụ: với không gây hại cho hiệu suất.

  • Nếu bạn cần các kết quả trung gian của nối cho một cái gì đó khác hơn là ăn các phiên bản kế tiếp của nối, StringBuilder không phải là sẽ giúp bạn. Ví dụ: nếu bạn tạo tên đầy đủ từ tên đầu tiên và họ, sau đó thêm thông tin thứ ba (có thể là biệt hiệu), bạn sẽ chỉ được hưởng lợi ích từ việc sử dụng StringBuilder nếu bạn không cần (tên đầu tiên + họ) chuỗi cho mục đích khác (như chúng tôi làm trong ví dụ tạo ra đối tượng Person).

  • Nếu bạn chỉ có một vài concatenations để làm, và bạn thực sự muốn làm cho họ trong báo cáo riêng biệt, nó không thực sự vấn đề mà cách bạn đi. Mà cách hiệu quả hơn sẽ phụ thuộc vào số lượng concatenations kích thước của chuỗi tham gia, trật tự những gì họ đang nối trong. Nếu bạn thực sự tin rằng đoạn mã để trở thành một hiệu suất nút cổ chai, hồ sơ hoặc điểm chuẩn theo cả hai cách.

8

System.String là một đối tượng bất biến - nó có nghĩa là bất cứ khi nào bạn sửa đổi nội dung của nó sẽ phân bổ một chuỗi mới và điều này cần có thời gian (và nhớ?). Sử dụng StringBuilder bạn sửa đổi nội dung thực tế của đối tượng mà không cần phân bổ một đối tượng mới.

Vì vậy, hãy sử dụng StringBuilder khi bạn cần thực hiện nhiều sửa đổi trên chuỗi.

4

Không có câu trả lời dứt khoát, chỉ có quy tắc-ngón tay cái. Quy tắc cá nhân của riêng tôi có dạng như sau:

  • Nếu ghép nối trong vòng lặp, hãy luôn sử dụng StringBuilder.
  • Nếu các chuỗi lớn, luôn sử dụng StringBuilder.
  • Nếu mã ghép nối gọn gàng và dễ đọc trên màn hình thì có thể là ok.
    Nếu không, hãy sử dụng StringBuilder.
+0

Tôi biết đây là một chủ đề cũ, nhưng tôi chỉ biết học tập và muốn biết những gì bạn coi là một "chuỗi lớn"? – MatthewD

2

Tôi không nghĩ rằng có một đường thẳng giữa thời điểm sử dụng hoặc khi không đến. Trừ khi tất nhiên ai đó thực hiện một số thử nghiệm rộng rãi để đi ra với các điều kiện vàng.

Đối với tôi, tôi sẽ không sử dụng StringBuilder nếu chỉ nối hai chuỗi lớn. Nếu có vòng lặp với số đếm không xác định, tôi có khả năng, ngay cả khi vòng lặp có thể là số lượng nhỏ.

+0

Thật vậy, nó sẽ hoàn toàn sai đối với ue StringBuilder để concat 2 chuỗi, nhưng đó là không có gì để làm với perf. thử nghiệm - đó chỉ đơn giản là sử dụng nó cho điều sai trái. –

3

Miễn là bạn có thể thể chất loại số lượng các kết nối (a + b + c ...), nó sẽ không tạo nên sự khác biệt lớn. N bình phương (tại N = 10) là sự giảm tốc 100X, điều này không quá tệ.

Vấn đề lớn là khi bạn đang nối hàng trăm chuỗi. Tại N = 100, bạn sẽ bị chậm lại 10000 lần. Đó là khá xấu.

4

Để diễn giải

Con sẽ đếm đến ba, không hơn, không kém. Ba là số bạn sẽ đếm, và số đếm sẽ là ba. Bốn ngươi không đếm, không đếm hai ngươi, ngoại trừ việc ngươi hãy lên ba. Sau khi số ba, là số thứ ba, đạt được, sau đó là lobbest thou thy của bạn Holy Hand Grenade of Antioch

Tôi thường sử dụng trình tạo chuỗi cho bất kỳ khối mã nào sẽ dẫn đến kết nối ba hoặc nhiều chuỗi.

+0

Tùy thuộc: Concetanation chỉ tạo một bản sao: "Russell" + "" + Steen + ".", Sẽ chỉ tạo một bản sao vì nó giữ nguyên độ dài của chuỗi trước đó. Chỉ khi bạn phải chia nối của bạn, bạn nên bắt đầu nghĩ về một người xây dựng – Peter

2
  • Nếu bạn nối chuỗi trong một vòng lặp, bạn nên xem xét sử dụng StringBuilder thay vì chuỗi thường xuyên
  • Trong trường hợp nó nối duy nhất, bạn có thể không thấy sự khác biệt trong thời gian thực hiện ở tất cả các

đây là một ứng dụng thử nghiệm đơn giản để chứng minh quan điểm:

class Program 
{ 
    static void Main(string[] args) 
    { 
     const int testLength = 30000; 
     var StartTime = DateTime.Now; 

     //TEST 1 - String 
     StartTime = DateTime.Now; 
     String tString = "test string"; 
     for (int i = 0; i < testLength; i++) 
     { 
      tString += i.ToString(); 
     } 
     Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); 
     //result: 2000 ms 

     //TEST 2 - StringBuilder 
     StartTime = DateTime.Now; 
     StringBuilder tSB = new StringBuilder("test string"); 
     for (int i = 0; i < testLength; i++) 
     { 
      tSB.Append(i.ToString()); 
     } 
     Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); 
     //result: 4 ms 

     Console.ReadLine(); 
    } 
} 

Kết quả:

0.123.
  • 30'000 lặp

    • Chuỗi - 2000 ms
    • StringBuilder - 4 ms
  • 1000 lặp

    • String - 2 ms
    • Stri ngBuilder - 1 ms
  • 500 lặp

    • String - 0 ms
    • StringBuilder - 0 ms
Các vấn đề liên quan