Chuỗi so với StringBuilder


215

Tôi hiểu sự khác biệt giữa StringStringBuilder( StringBuildercó thể thay đổi) nhưng có sự khác biệt lớn về hiệu suất giữa hai loại không?

Chương trình tôi đang làm việc có rất nhiều trường hợp nối chuỗi điều khiển (500+). Là sử dụng StringBuildermột sự lựa chọn tốt hơn?

Câu trả lời:


236

Vâng, sự khác biệt hiệu suất là đáng kể. Xem bài viết KB " Cách cải thiện hiệu suất nối chuỗi trong Visual C # ".

Tôi đã luôn cố gắng viết mã cho rõ ràng trước, và sau đó tối ưu hóa cho hiệu suất sau này. Điều đó dễ dàng hơn nhiều so với cách khác! Tuy nhiên, khi thấy sự khác biệt hiệu năng rất lớn trong các ứng dụng của tôi giữa hai ứng dụng, bây giờ tôi nghĩ về nó cẩn thận hơn một chút.

May mắn thay, việc phân tích hiệu suất trên mã của bạn tương đối đơn giản để xem bạn đang dành thời gian ở đâu và sau đó sửa đổi nó để sử dụng StringBuilderkhi cần thiết.


44
Một nguyên tắc nhỏ là sử dụng Chuỗi khi bạn không thay đổi và sử dụng StringBuilder nếu bạn sẽ thay đổi.
Tim

31
Tôi thích câu trả lời này rất nhiều, đặc biệt là lời khuyên để viết mã cho rõ ràng trước khi thực hiện. Là nhà phát triển, chúng tôi dành nhiều hoặc nhiều thời gian để đọc mã như chúng tôi viết nó.
Scott Lawrence

Outlaw: Tôi nghĩ rằng nên trở thành câu trả lời của riêng mình được bình chọn riêng, nếu tôi hiểu chính xác StackOverflow.
Jay Bazuzi

2
dựa trên kinh nghiệm của tôi nếu bạn cố gắng nối khoảng 10-15 chuỗi thì bạn có thể đi với chuỗi nhưng nếu không. chuỗi nhiều hơn thế, sau đó sử dụng trình tạo chuỗi
Peeyush

3
Nó vẫn phụ thuộc vào cách người ta sử dụng nó, để tham khảo các thử nghiệm thực sự tôi thích Mã hóa kinh dị - Thảm kịch buồn của Nhà hát Tối ưu hóa vi mô
Erik Philips

56

Để làm rõ những gì Chung Hân Đồng nói về 4 chuỗi, nếu bạn có một cái gì đó như thế này:

string a,b,c,d;
 a = b + c + d;

sau đó nó sẽ nhanh hơn bằng cách sử dụng các chuỗi và toán tử cộng. Điều này là do (như Java, như Eric chỉ ra), bên trong nó sử dụng StringBuilder tự động (Trên thực tế, nó sử dụng một nguyên thủy mà StringBuilder cũng sử dụng)

Tuy nhiên, nếu những gì bạn đang làm gần hơn với:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

Sau đó, bạn cần sử dụng StringBuilder một cách rõ ràng. .Net không tự động tạo StringBuilder ở đây, vì nó sẽ là vô nghĩa. Ở cuối mỗi dòng, "a" phải là một chuỗi (không thay đổi), do đó, nó sẽ phải tạo và loại bỏ StringBuilder trên mỗi dòng. Để tăng tốc, bạn cần sử dụng cùng StringBuilder cho đến khi bạn hoàn thành việc xây dựng:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();

5
Không có lý do tại sao trình biên dịch C # cần xử lý mẫu thứ hai khác với mẫu đầu tiên. Đặc biệt, không có nghĩa vụ phải tạo ra một chuỗi ở cuối mỗi dòng. Trình biên dịch có thể hoạt động như bạn nói, nhưng không có nghĩa vụ phải làm như vậy.
CodeInChaos

@CodesInChaos, một biến chuỗi bất biến đang được gán cụ thể ở cuối mỗi dòng, không tạo ra nghĩa vụ tạo ra một chuỗi? Tuy nhiên, tôi đồng ý với quan điểm rằng không có lý do nào để đối xử với từng dòng riêng biệt khác nhau (và tôi không chắc là có hay không), việc giảm hiệu suất đến từ việc phân bổ lại, vì vậy điều đó không thành vấn đề.
Saeb Amini

@SaebAmini - Nếu alà một biến cục bộ và đối tượng mà nó tham chiếu chưa được gán cho một biến khác (có thể truy cập được vào một luồng khác), một trình tối ưu hóa tốt có thể xác định rằng akhông được truy cập bởi bất kỳ mã nào khác trong chuỗi này dòng; chỉ giá trị cuối cùng của avấn đề. Vì vậy, nó có thể coi ba dòng mã đó như thể chúng được viết a = b + c + d;.
ToolmakerSteve

29

StringBuilder tốt hơn là NẾU bạn đang thực hiện nhiều vòng lặp hoặc các nhánh trong mã của bạn vượt qua ... tuy nhiên, đối với hiệu suất PURE, nếu bạn có thể thoát khỏi khai báo chuỗi SINGLE , thì điều đó hiệu quả hơn nhiều.

Ví dụ:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

hiệu quả hơn

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

Trong trường hợp này, StringBuild có thể được coi là dễ bảo trì hơn, nhưng không hiệu quả hơn so với khai báo chuỗi đơn.

9 trong số 10 lần mặc dù ... sử dụng trình tạo chuỗi.

Một lưu ý phụ: chuỗi + var cũng hiệu quả hơn khi tiếp cận chuỗi.Format (nói chung) sử dụng StringBuilder bên trong (khi nghi ngờ ... hãy kiểm tra bộ phản xạ!)


17
Tôi muốn bạn nói làm thế nào bạn biết điều đó / làm thế nào để xác minh điều đó.
ChrisW

2
Bạn không xác minh hiệu suất trong bộ phản xạ: Bạn xác minh hiệu suất bằng mã phát hành thời gian, phân tích với trình lược tả và tìm kiếm lời giải thích với bộ phản xạ.
Albin Sunnanbo

3
Cân nhắc sử dụng String.Format () để nối một số lượng nhỏ các chuỗi nhỏ, đặc biệt là mục tiêu là định dạng các thông báo để hiển thị cho người dùng.
Gary Kindel

1
Đây là thông tin rất xấu. ("chuỗi myString có hiệu suất cao hơn") hoàn toàn không đúng.
Tom Stickel

3
Thông tin trong câu trả lời này là không chính xác. StringBuilder nhanh hơn một chút so với ghép được thực hiện trong cùng một câu lệnh; tuy nhiên, bạn sẽ chỉ nhận thấy sự khác biệt giữa hai loại nếu bạn thực hiện hàng trăm nghìn lần ( Nguồn ). Như đã nói trong nguồn, "nó không thành vấn đề!"
David Sherret

25

Một ví dụ đơn giản để chứng minh sự khác biệt về tốc độ khi sử dụng Stringphép nối so với StringBuilder:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

Kết quả:

Sử dụng nối chuỗi: 15423 mili giây

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

Kết quả:

Sử dụng StringBuilder: 10 mili giây

Kết quả là lần lặp đầu tiên mất 15423 ms trong khi lần lặp thứ hai sử dụng StringBuildermất 10 ms.

Theo tôi thì việc sử dụng StringBuildernhanh hơn, nhanh hơn rất nhiều.


24

Điểm chuẩn này cho thấy việc nối thường xuyên sẽ nhanh hơn khi kết hợp 3 chuỗi hoặc ít hơn.

http://www.chinhdo.com/20070224/opesbuilder-is-not-always-faster/

StringBuilder có thể cải thiện đáng kể việc sử dụng bộ nhớ, đặc biệt là trong trường hợp bạn thêm 500 chuỗi với nhau.

Hãy xem xét ví dụ sau:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

Điều gì xảy ra trong bộ nhớ? Các chuỗi sau đây được tạo:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

Bằng cách thêm năm số đó vào cuối chuỗi, chúng tôi đã tạo ra 13 đối tượng chuỗi! Và 12 người trong số họ là vô dụng! Ồ

StringBuilder khắc phục vấn đề này. Nó không phải là "chuỗi có thể thay đổi" như chúng ta thường nghe ( tất cả các chuỗi trong .NET là bất biến ). Nó hoạt động bằng cách giữ một bộ đệm nội bộ, một mảng char. Gọi Append () hoặc AppendLine () thêm chuỗi vào khoảng trống ở cuối mảng char; nếu mảng quá nhỏ, nó tạo ra một mảng mới, lớn hơn và sao chép bộ đệm ở đó. Vì vậy, trong ví dụ trên, StringBuilder có thể chỉ cần một mảng duy nhất để chứa tất cả 5 bổ sung cho chuỗi - tùy thuộc vào kích thước bộ đệm của nó. Bạn có thể cho StringBuilder biết bộ đệm của nó sẽ lớn như thế nào trong hàm tạo.


2
Nit nhỏ: hơi kỳ quặc khi nói "chúng tôi đã tạo ra 13 đối tượng chuỗi và 12 trong số đó là vô dụng", và sau đó để nói StringBuilder khắc phục vấn đề này. Rốt cuộc, sáu trong số các chuỗi bạn không có lựa chọn nào khác ngoài việc tạo ra; họ đến từ i.ToString(). Vì vậy, với StringBuilder, bạn vẫn phải tạo các chuỗi 6 + 1; nó giảm tạo 13 chuỗi để tạo 7 chuỗi. Nhưng đó vẫn là cách nhìn sai lầm; việc tạo ra chuỗi sáu số không liên quan. Dòng dưới cùng: đơn giản là bạn không nên đề cập đến sáu chuỗi được tạo bởi i.ToString(); chúng không phải là một phần của so sánh hiệu quả.
ToolmakerSteve

12

Có, StringBuildercho hiệu suất tốt hơn trong khi thực hiện thao tác lặp lại qua một chuỗi. Đó là bởi vì tất cả các thay đổi được thực hiện cho một thể hiện duy nhất nên nó có thể tiết kiệm rất nhiều thời gian thay vì tạo một thể hiện mới như thế nào String.

Chuỗi Vs Stringbuilder

  • String

    1. trong Systemkhông gian tên
    2. trường hợp bất biến (chỉ đọc)
    3. hiệu suất suy giảm khi thay đổi liên tục của giá trị xảy ra
    4. chủ đề an toàn
  • StringBuilder (chuỗi đột biến)

    1. trong System.Textkhông gian tên
    2. trường hợp đột biến
    3. cho thấy hiệu suất tốt hơn vì những thay đổi mới được thực hiện cho thể hiện hiện tại

Rất khuyến khích bài viết mob dotnet: String Vs StringBuilder trong C # .

Câu hỏi tràn ngăn xếp liên quan: Khả năng biến đổi của chuỗi khi chuỗi không thay đổi trong C #? .


12

Trình tạo chuỗi Vs Chuỗi:

Điều đầu tiên bạn phải biết rằng trong cuộc tập hợp hai lớp này sống?

Vì thế,

chuỗi có mặt trong Systemkhông gian tên.

StringBuilder có mặt trong System.Textkhông gian tên.

Đối với khai báo chuỗi :

Bạn phải bao gồm Systemkhông gian tên. một cái gì đó như thế này Using System;

Đối với khai báo StringBuilder :

Bạn phải bao gồm System.textkhông gian tên. một cái gì đó như thế này Using System.text;

Bây giờ hãy đến câu hỏi thực tế.

Sự khác biệt giữa chuỗi & StringBuilder là gì?

Sự khác biệt chính giữa hai điều này là:

chuỗi là bất biến.

StringBuilder có thể thay đổi.

Vì vậy, bây giờ hãy thảo luận về sự khác biệt giữa bất biến và đột biến

Mutable :: có nghĩa là có thể thay đổi.

Bất biến :: có nghĩa là Không thể thay đổi.

Ví dụ:

using System;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // String Example

            string name = "Rehan";
            name = name + "Shah";
            name = name + "RS";
            name = name + "---";
            name = name + "I love to write programs.";

            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah RS --- I love to write programs."
        }
    }
}

Vì vậy, trong trường hợp này, chúng ta sẽ thay đổi cùng một đối tượng 5 lần.

Vì vậy, câu hỏi hiển nhiên là vậy! Điều gì thực sự xảy ra dưới mui xe, khi chúng ta thay đổi cùng một chuỗi 5 lần.

Đây là những gì xảy ra khi chúng ta thay đổi cùng một chuỗi 5 lần.

Hãy nhìn vào hình.

nhập mô tả hình ảnh ở đây

Giải thích:

Khi chúng tôi lần đầu tiên khởi tạo biến "name" này thành "Rehan", tức là string name = "Rehan" biến này được tạo trên stack "name" và trỏ đến giá trị "Rehan" đó. sau khi dòng này được thực thi: "name = name +" Shah ". biến tham chiếu không còn trỏ đến đối tượng đó" Rehan "mà bây giờ nó trỏ đến" Shah ", v.v.

Vì vậy, stringý nghĩa bất di bất dịch là một khi chúng ta tạo đối tượng trong bộ nhớ, chúng ta không thể thay đổi chúng.

Vì vậy, khi chúng ta kết hợp namebiến, đối tượng trước đó vẫn còn đó trong bộ nhớ và một đối tượng chuỗi mới khác sẽ được tạo ...

Vì vậy, từ hình trên, chúng ta có năm đối tượng, bốn đối tượng bị vứt đi, chúng hoàn toàn không được sử dụng. Họ vẫn còn trong bộ nhớ và họ chiếm số lượng bộ nhớ. "Garbage Collector" chịu trách nhiệm cho việc dọn sạch các tài nguyên từ bộ nhớ.

Vì vậy, trong trường hợp chuỗi bất cứ lúc nào khi chúng ta thao tác chuỗi nhiều lần, chúng ta có một số đối tượng được tạo Ans ở đó trong bộ nhớ.

Vì vậy, đây là câu chuyện của chuỗi biến.

Bây giờ, hãy nhìn về phía StringBuilder Object. Ví dụ:

using System;
using System.Text;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // StringBuilder Example

            StringBuilder name = new StringBuilder();
            name.Append("Rehan");
            name.Append("Shah");
            name.Append("RS");
            name.Append("---");
            name.Append("I love to write programs.");


            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah Rs --- I love to write programs."
        }
    }
}

Vì vậy, trong trường hợp này, chúng ta sẽ thay đổi cùng một đối tượng 5 lần.

Vì vậy, câu hỏi hiển nhiên là vậy! Điều gì thực sự xảy ra dưới mui xe, khi chúng tôi thay đổi cùng một StringBuilder 5 lần.

Đây là những gì xảy ra khi chúng ta thay đổi cùng một StringBuilder 5 lần.

Hãy nhìn vào hình. nhập mô tả hình ảnh ở đây

Giải thích: Trong trường hợp đối tượng StringBuilder. bạn sẽ không có được đối tượng mới. Cùng một đối tượng sẽ được thay đổi trong bộ nhớ, vì vậy ngay cả khi bạn thay đổi đối tượng và nói 10.000 lần, chúng ta vẫn sẽ chỉ có một đối tượng stringBuilder.

Bạn không có nhiều đối tượng rác hoặc các đối tượng StringBuilder không tham số vì tại sao nó có thể thay đổi. Nó có thể thay đổi có nghĩa là nó thay đổi theo thời gian?

Sự khác biệt:

  • Chuỗi có mặt trong không gian tên Hệ thống trong đó Stringbuilder hiện diện trong không gian tên System.Text.
  • chuỗi là bất biến trong đó StringBuilder là mutabe.

8

StringBuilder giảm số lượng phân bổ và bài tập, với chi phí sử dụng thêm bộ nhớ. Được sử dụng đúng cách, nó có thể loại bỏ hoàn toàn nhu cầu của trình biên dịch để phân bổ các chuỗi lớn hơn và lớn hơn cho đến khi kết quả được tìm thấy.

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

so với

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once

5

Hiệu năng của hoạt động nối cho đối tượng String hoặc StringBuilder phụ thuộc vào tần suất phân bổ bộ nhớ xảy ra. Hoạt động nối chuỗi luôn phân bổ bộ nhớ, trong khi đó hoạt động nối chuỗi StringBuilder chỉ cấp phát bộ nhớ nếu bộ đệm đối tượng StringBuilder quá nhỏ để chứa dữ liệu mới. Do đó, lớp String thích hợp hơn cho hoạt động nối nếu một số đối tượng Chuỗi cố định được nối. Trong trường hợp đó, các hoạt động nối riêng lẻ thậm chí có thể được kết hợp thành một hoạt động duy nhất bởi trình biên dịch. Một đối tượng StringBuilder thích hợp hơn cho hoạt động nối nếu một số chuỗi tùy ý được nối; ví dụ: nếu một vòng lặp nối một số chuỗi ngẫu nhiên đầu vào của người dùng.

Nguồn: MSDN


3

StringBuilder là tốt hơn để xây dựng một chuỗi từ nhiều giá trị không cố định.

Nếu bạn đang xây dựng một chuỗi từ nhiều giá trị không đổi, chẳng hạn như nhiều dòng giá trị trong tài liệu HTML hoặc XML hoặc các đoạn văn bản khác, bạn có thể thoát khỏi việc chỉ nối vào cùng một chuỗi, vì hầu hết tất cả các trình biên dịch đều làm "Gấp liên tục", một quá trình giảm cây phân tích khi bạn có một loạt các thao tác liên tục (nó cũng được sử dụng khi bạn viết một cái gì đó như int minutesPerYear = 24 * 365 * 60). Và đối với các trường hợp đơn giản với các giá trị không cố định được nối với nhau, trình biên dịch .NET sẽ giảm mã của bạn thành một cái gì đó tương tự như những gì StringBuilder.

Nhưng khi phần bổ sung của bạn không thể được giảm xuống một cái gì đó đơn giản hơn bởi trình biên dịch, bạn sẽ muốn a StringBuilder. Như fizch chỉ ra, điều đó có nhiều khả năng xảy ra bên trong một vòng lặp.


2

Tôi tin rằng StringBuilder nhanh hơn nếu bạn có nhiều hơn 4 chuỗi bạn cần nối lại với nhau. Thêm vào đó, nó có thể làm một số thứ hay ho như AppendLine.


2

Trong .NET, StringBuilder vẫn nhanh hơn so với nối thêm chuỗi. Tôi khá chắc chắn rằng trong Java, họ chỉ tạo StringBuffer dưới mui xe khi bạn nối các chuỗi, vì vậy thực sự không có sự khác biệt. Tôi không chắc tại sao họ chưa làm điều này trong .NET.



2

Sử dụng chuỗi để nối có thể dẫn đến độ phức tạp thời gian chạy theo thứ tự O(n^2).

Nếu bạn sử dụng một StringBuilder, việc sao chép bộ nhớ phải được thực hiện ít hơn rất nhiều. Với StringBuilder(int capacity)hiệu suất bạn có thể tăng hiệu suất nếu bạn có thể ước tính trận chung kết Stringsẽ diễn ra lớn như thế nào . Ngay cả khi bạn không chính xác, có lẽ bạn sẽ chỉ phải tăng khả năng của StringBuildermột vài lần mà còn có thể giúp hiệu suất.


2

Tôi đã thấy hiệu suất tăng đáng kể từ việc sử dụng lệnh EnsureCapacity(int capacity)gọi phương thức trên một thể hiện StringBuildertrước khi sử dụng nó cho bất kỳ lưu trữ chuỗi nào. Tôi thường gọi nó trên dòng mã sau khi khởi tạo. Nó có tác dụng tương tự như khi bạn khởi tạo StringBuildernhư thế này:

var sb = new StringBuilder(int capacity);

Cuộc gọi này phân bổ bộ nhớ cần thiết trước thời hạn, điều này gây ra việc phân bổ bộ nhớ ít hơn trong nhiều Append()hoạt động. Bạn phải đưa ra một phỏng đoán có giáo dục về số lượng bộ nhớ bạn sẽ cần, nhưng đối với hầu hết các ứng dụng, điều này không quá khó. Tôi thường mắc lỗi về phía bộ nhớ quá nhiều (chúng ta đang nói 1k hoặc hơn).


Không cần phải gọi EnsureCapacityngay sau khi StringBuilderkhởi tạo. Đơn giản chỉ cần khởi tạo StringBuildernhư thế này : var sb = new StringBuilder(int capacity).
David Ferenczy Rogožan

Tôi đã nói rằng nó giúp sử dụng một số nguyên tố.
Karl Gjertsen

1

Hơn nữa với các câu trả lời trước, điều đầu tiên tôi luôn làm khi nghĩ về các vấn đề như thế này là tạo ra một ứng dụng thử nghiệm nhỏ. Trong ứng dụng này, thực hiện một số thử nghiệm thời gian cho cả hai kịch bản và tự mình xem cái nào nhanh hơn.

IMHO, nối thêm 500 mục nhập chuỗi chắc chắn nên sử dụng StringBuilder.


1

String và StringBuilder thực sự là cả hai bất biến, StringBuilder đã tích hợp sẵn bộ đệm cho phép kích thước của nó được quản lý hiệu quả hơn. Khi StringBuilder cần thay đổi kích thước là khi nó được phân bổ lại trên heap. Theo mặc định, nó có kích thước đến 16 ký tự, bạn có thể đặt cái này trong hàm tạo.

ví dụ.

StringBuilder sb = new StringBuilder (50);


2
Không chắc chắn rằng bạn hiểu những gì có nghĩa là bất biến. Chuỗi là bất biến, chúng KHÔNG THỂ được thay đổi. Bất cứ điều gì "thay đổi" thực sự chỉ là giá trị cũ vẫn còn trên heap mà không có con trỏ nào để xác định vị trí của nó. StringBuilder (mutable) là kiểu tham chiếu trên heap, con trỏ tới heap được thay đổi và phân bổ không gian cho thay đổi này.
Tom Stickel

1

Chuỗi nối sẽ chi phí bạn nhiều hơn. Trong Java, Bạn có thể sử dụng StringBuffer hoặc StringBuilder dựa trên nhu cầu của bạn. Nếu bạn muốn triển khai an toàn và đồng bộ hóa luồng, hãy truy cập StringBuffer. Điều này sẽ nhanh hơn so với nối chuỗi.

Nếu bạn không cần triển khai an toàn đồng bộ hóa hoặc luồng, hãy truy cập StringBuilder. Điều này sẽ nhanh hơn so với nối chuỗi và cũng nhanh hơn StringBuffer vì chúng không có chi phí đồng bộ hóa.


0

StringBuilder có lẽ là thích hợp hơn. Lý do là nó phân bổ nhiều không gian hơn mức cần thiết hiện tại (bạn đặt số lượng ký tự) để chừa chỗ cho các phụ lục trong tương lai. Sau đó, những phụ kiện tương lai phù hợp với bộ đệm hiện tại không yêu cầu bất kỳ phân bổ bộ nhớ hoặc bộ sưu tập rác nào, có thể tốn kém. Nói chung, tôi sử dụng StringBuilder để ghép chuỗi phức tạp hoặc định dạng nhiều, sau đó chuyển đổi thành Chuỗi bình thường khi dữ liệu hoàn tất và tôi muốn một đối tượng bất biến một lần nữa.


0

Nếu bạn đang thực hiện nhiều phép nối chuỗi, hãy sử dụng StringBuilder. Khi bạn nối với một Chuỗi, bạn tạo một Chuỗi mới mỗi lần, sử dụng thêm bộ nhớ.

Alex


0

Theo nguyên tắc chung, nếu tôi phải đặt giá trị của chuỗi nhiều lần hoặc nếu có bất kỳ phần phụ nào vào chuỗi, thì nó cần phải là trình tạo chuỗi. Tôi đã thấy các ứng dụng mà tôi đã viết trong quá khứ trước khi tìm hiểu về các nhà xây dựng chuỗi đã có một dấu chân bộ nhớ khổng lồ dường như tiếp tục phát triển và tăng trưởng. Việc thay đổi các chương trình này để sử dụng trình tạo chuỗi giúp giảm đáng kể việc sử dụng bộ nhớ. Bây giờ tôi thề bởi người xây dựng chuỗi.



0

StringBuilder hiệu quả hơn đáng kể nhưng bạn sẽ không thấy hiệu suất đó trừ khi bạn đang thực hiện một số lượng lớn sửa đổi chuỗi.

Dưới đây là một đoạn mã nhanh để đưa ra một ví dụ về hiệu suất. Như bạn có thể thấy bạn thực sự chỉ bắt đầu thấy sự gia tăng hiệu suất lớn khi bạn có được các bước lặp lớn.

Như bạn có thể thấy 200.000 lần lặp mất 22 giây trong khi 1 triệu lần lặp sử dụng StringBuildergần như ngay lập tức.

string s = string.Empty;
StringBuilder sb = new StringBuilder();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 50000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 200000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());

for (int i = 0; i <= 1000000; i++)
{
    sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());

Console.ReadLine();

Kết quả của đoạn mã trên:

Chuỗi bắt đầu + lúc 28/01/2013 16:55:40.

Kết thúc chuỗi + lúc 28/01/2013 16:55:40.

Chuỗi bắt đầu + lúc 28/01/2013 16:55:40.

Kết thúc chuỗi + lúc 28/01/2013 16:56:02.

Bắt đầu Sb nối vào ngày 28/01/2013 16:56:02.

Kết thúc Sb nối vào ngày 28/01/2013 16:56:02.


1
Nếu Trình xây dựng chuỗi rất mạnh thì tại sao chúng ta có Chuỗi tồn tại. Tại sao chúng ta không xóa sạch String. Tôi đã hỏi câu hỏi này để bạn có thể cho tôi biết LỢI ÍCH của Chuỗi trên StringBuilder
Không thể phá vỡ vào

-2

StringBuilder sẽ hoạt động tốt hơn, từ điểm đứng bộ nhớ. Đối với việc xử lý, sự khác biệt về thời gian thực hiện có thể không đáng kể.

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.