2009-02-02 42 views
6

StringBuilder có một danh tiếng như là một công cụ thao tác chuỗi nhanh hơn so với chỉ đơn giản là nối chuỗi. Cho dù điều đó có đúng hay không, tôi vẫn tự hỏi về kết quả của các hoạt động của StringBuilder và các chuỗi chúng tạo ra.Chuỗi StringBuilder có thay đổi không?

Một cách nhanh chóng jaunt vào Reflector cho thấy rằng StringBuilder.ToString() không phải luôn luôn trả về một bản sao, đôi khi nó dường như trả về một thể hiện của chuỗi nội bộ. Nó cũng có vẻ sử dụng một số chức năng nội bộ để thao tác các chuỗi nội bộ.

Vì vậy, tôi phải làm gì nếu tôi làm điều này?

string s = "Yo Ho Ho"; 
StringBuilder sb = new StringBuilder(s); 
string newString = sb.ToString(); 
sb.Append(" and a bottle of rum."); 
string newNewString = sb.ToString(); 

Có phải newString và newNewString trường hợp chuỗi khác nhau hoặc giống nhau không? Tôi đã cố gắng để tìm ra điều này thông qua phản xạ, và tôi chỉ không hoàn toàn hiểu mọi thứ.

Làm thế nào về mã này?

StringBuilder sb = new StringBuilder("Foo\n"); 
StringReader sr = new StringReader(sb.ToString()); 
string s = sr.ReadLine(); 
sb.Append("Bar\n"); 
s = sr.ReadLine(); 

Câu lệnh cuối cùng sẽ trả về null hoặc "Bar"? Và nếu nó trả về một hoặc khác, thì hành vi được xác định hoặc không xác định này? Nói cách khác, tôi có thể dựa vào nó?

Tài liệu này rất đáng kể về chủ đề này và tôi không muốn dựa vào hành vi được quan sát theo đặc điểm kỹ thuật.

+0

Xin lưu ý rằng việc triển khai StringBuilder đã thay đổi kể từ khi câu hỏi này được hỏi và trả lời. – mayu

Trả lời

10

Bên ngoài mscorlib, bất kỳ phiên bản nào của System.String đều không thay đổi, thời gian.

StringBuilder thực hiện một số thao tác thú vị của Strings trong nội bộ nhưng vào cuối ngày, nó sẽ không trả lại chuỗi cho bạn và sau đó biến đổi chuỗi theo cách hiển thị cho mã của bạn.

Để xem liệu các cuộc gọi tiếp theo đến StringBuilder.ToString() có trả về cùng một thể hiện của một chuỗi hay một chuỗi khác nhau có cùng giá trị hay không, đó là thực thi phụ thuộc và bạn không nên dựa vào hành vi này.

+0

Có, thử nghiệm đã cho thấy điều này là đúng, nhưng gameunking trong internals với Reflector đã không hiển thị một lý do rõ ràng lý do tại sao. Nó xuất hiện để trả về một tham chiếu đến chuỗi nội bộ trên mỗi cuộc gọi, do đó sự nhầm lẫn của tôi là liệu chuỗi có thể thay đổi hay không. –

+0

@ Mystere, Việc thực hiện StringBuilder là một chút khó khăn lúc đầu tiên. Cho đến khi tôi đọc câu hỏi của bạn và bắt đầu khám phá, tôi đã không nhận ra rằng họ đã tạo bộ nhớ đệm cấp luồng. Tôi dự định sẽ có một cái nhìn dài hơn tối nay (hoặc ngày mai). Nhưng bạn có thể tin tưởng vào chuỗi kết quả là bất biến – JaredPar

4

newStringnewNewString là các trường hợp chuỗi khác nhau.

Mặc dù ToString() trả về chuỗi hiện tại, nó xóa biến chủ đề hiện tại của nó. Điều đó có nghĩa là lần sau bạn nối thêm, nó sẽ lấy một bản sao của chuỗi hiện tại trước khi thêm.

Tôi không phải là hoàn toàn chắc chắn bạn đang nhận được gì trong câu hỏi thứ hai của mình, nhưng s sẽ là rỗng: nếu ký tự cuối cùng trong tệp là ký tự chấm dứt dòng cho dòng trước đó, dòng là không phải được coi là có dòng trống giữa các ký tự đó và phần cuối của tệp. Chuỗi đã được đọc trước đây không có sự khác biệt về điều này.

+0

Ahh .. bạn giải thích bí ẩn đối với tôi. Việc xóa biến chủ đề là nguyên nhân khiến bản sao được thêm vào, cách đơn giản nhưng không rõ ràng. Câu hỏi thứ hai của tôi là một biến thể về câu hỏi biến đổi, liên quan đến một tham chiếu được lưu trữ trong StringReader. –

2

Toàn bộ mục đích của lớp này là làm cho chuỗi có thể thay đổi được, vì vậy thực tế là. Tôi tin rằng (nhưng không chắc chắn) nó sẽ trả lại cùng một chuỗi mà đi vào nó chỉ khi không có gì khác đã được thực hiện với đối tượng này. Vì vậy, sau

String s_old = "Foo"; 
StringBuilder sb = new StringBuilder(s_old); 
String s_new = sb.ToString(); 

s_old sẽ giống như s_new nhưng sẽ không có trong trường hợp nào khác.

Tôi cần lưu ý rằng, đối với trình biên dịch Java sẽ tự động chuyển đổi nhiều chuỗi bổ sung thành các hoạt động với lớp StringBuilder (hoặc StringBuffer tương tự nhưng thậm chí nhanh hơn) và tôi sẽ thực sự ngạc nhiên.Trình biên dịch NET cũng không thực hiện chuyển đổi này.

+0

Trình biên dịch C# không sử dụng StringBuilder cho các chuỗi nối - nó sử dụng String.Concat. Điều đó có nghĩa là độ dài cuối cùng được biết trước khi thực hiện bất kỳ kết nối nào. –

3

Are newStringnewNewString khác nhau string trường hoặc giống nhau không? Tôi đã cố gắng để con số này ra thông qua phản xạ, và tôi chỉ không hoàn toàn hiểu mọi thứ.

Họ khác string trường hợp: newString là "Yo Ho Ho" và newNewString là "Yo Ho Ho and a bottle of rum.". strings là không thay đổi và khi bạn gọi StringBuilder.ToString(), phương thức trả về string bất biến thể hiện trạng thái hiện tại.

Câu lệnh cuối cùng trả về null hoặc "Bar"? Và nếu nó trả về một hoặc có khác, hành vi này được xác định hoặc không xác định ? Nói cách khác, tôi có thể dựa vào số trên đó không?

Nó sẽ trả lại null. Các StringReader đang làm việc trên bất biến string bạn đã truyền cho nó tại nhà xây dựng, do đó, nó không bị ảnh hưởng bởi bất cứ điều gì bạn làm với StringBuilder.

Các vấn đề liên quan