2012-02-03 24 views
8

thể trùng lặp:
Why is String.Concat not optimized to StringBuilder.Append?Tại sao chuỗi không nối được tự động chuyển thành StringBuilder trong C#?

Một ngày nào đó tôi được ranting về một điều khiển Telerik đặc biệt đến một người bạn của tôi. Tôi nói với anh ta rằng phải mất vài giây để tạo ra một cây điều khiển, và sau khi profiling tôi phát hiện ra rằng nó đang sử dụng một chuỗi nối trong một vòng lặp thay vì một StringBuilder. Sau khi viết lại nó hoạt động gần như ngay lập tức.

Vì vậy, bạn tôi đã nghe điều đó và dường như ngạc nhiên khi trình biên dịch C# không thực hiện chuyển đổi đó tự động như trình biên dịch Java. Đọc nhiều câu trả lời của Eric Lippert Tôi nhận thấy rằng tính năng này không làm cho nó bởi vì nó không được coi là xứng đáng. Nhưng nếu, theo giả thuyết, chi phí là nhỏ để thực hiện nó, lý do gì sẽ ngăn chặn một từ làm việc đó?

+2

Không có gì ngăn cản bạn thực hiện tối ưu hóa kỹ thuật này, nhưng hãy xem xét hai thao tác không tương đương về mặt ngữ nghĩa. Việc ghép nối một 'string' trả về một đối tượng' string' mới là kết quả của phép toán, trong khi sử dụng 'StringBuilder' sẽ sửa đổi đối tượng chuỗi hiện có. Phân tích mã sẽ phải được thực hiện để đảm bảo rằng bạn không có bất kỳ cách nào dựa vào tác dụng phụ của việc nối. Trong hầu hết các trường hợp, bạn không phải như vậy, đây không phải là vấn đề không thể khắc phục, nhưng sau đó, không khó để viết mã một cách chính xác ngay từ đầu. –

+1

Xem thêm http://blogs.msdn.com/b/ericlippert/archive/2011/07/19/strings-immutability-and-persistence.aspx – SLaks

+1

cũng xem bài đăng này: http: //pranayamr.blogspot. com/2011/02/why-to-user-stringbuilder-over-string.html –

Trả lời

9

Tôi lưu ý rằng đây là một bản sao chính xác của

Why is String.Concat not optimized to StringBuilder.Append?

vì vậy đây có lẽ nên được đóng lại.

Nhưng nếu, về mặt lý thuyết, chi phí là nhỏ để thực hiện, lý do nào sẽ ngăn không cho thực hiện?

Có vẻ như bạn đang đề xuất một chút kiến ​​thức: nếu không có lý do gì để không làm X, thì có lý do gì để không làm X không? Số

Tôi thấy ít giá trị khi biết câu trả lời cho các câu hỏi giả định, phản tác dụng. Có lẽ câu hỏi hay hơn để đặt ra sẽ là câu hỏi về thế giới thực:

Có ngôn ngữ lập trình nào sử dụng tối ưu hóa này không?

Có. Trong JScript.NET, chúng tôi phát hiện chuỗi nối trong các vòng lặp và trình biên dịch biến chúng thành các cuộc gọi đến trình tạo chuỗi.

Đó sau đó có thể được theo dõi với:

một số khác biệt giữa JScript .NET và C# mà biện minh cho việc tối ưu hóa trong một ngôn ngữ nhưng không phải trong khác là gì?

Giả định cốt lõi của JScript.NET là các lập trình viên của nó hầu hết là các lập trình viên JavaScript, và nhiều người trong số họ sẽ xây dựng các thư viện phải chạy trong bất kỳ việc thực hiện ECMAScript nào. Những lập trình viên này có thể không biết rõ về .NET framework, và thậm chí nếu họ làm, họ có thể không thể sử dụng StringBuilder mà không làm cho mã thư viện của họ không di chuyển được. Nó cũng hợp lý để giả định rằng các lập trình viên JavaScript có thể là lập trình viên mới làm quen, hoặc lập trình viên đến lập trình thông qua ngành nghề của họ thay vì một khóa học về khoa học máy tính.

Các lập trình viên C# có nhiều khả năng biết rõ hơn về khuôn khổ .NET, để viết các thư viện hoạt động với khung công tác, và là những người lập trình có kinh nghiệm hiểu tại sao ghép chuỗi lặp lại là O (n) . Họ cần tối ưu hóa này được tạo bởi trình biên dịch ít hơn vì họ chỉ có thể tự làm nếu họ cho là cần thiết.

Tóm lại: các tính năng của trình biên dịch là chi tiêu ngân sách của chúng tôi để tăng thêm giá trị cho khách hàng; bạn nhận được nhiều hơn "bang cho buck" thêm tính năng này vào JScript.NET hơn là bạn thêm nó vào C#.

+0

cảm ơn bạn đã trả lời. Tuy nhiên, tôi chưa đề xuất một nghiên cứu. Đôi khi các tính năng không được thêm vào vì lý do ý thức hệ, không chỉ chi phí thuần túy (để thiết kế, thực hiện, kiểm tra). Ví dụ: bạn đã tự tuyên bố rằng C# không bao gồm phần mở rộng .ForEach đơn giản vì nó sẽ giới thiệu sự mơ hồ không cần thiết. Chi phí để thêm oneliner này là rất nhỏ, nhưng lý do không liên quan đến chúng. Nhưng tôi nghĩ kết luận cuối cùng của bạn là một lý lẽ thỏa đáng để tôi sử dụng với bạn tôi. –

+0

@RomanR: Tôi hoài nghi về điều đó. Bạn có thể đưa ra một ví dụ về một quyết định ý thức hệ mà không phải sự thật cũng cấu thành một quyết định dựa trên chi phí không? – Brian

+0

@Brian: Ví dụ của RomanR là một ví dụ hay; chúng tôi có thể làm một phương pháp mở rộng ForEach trên 'IEnumerable 'với chi phí rất thấp, và một số lợi ích nhưng với tâm trí của tôi, nó không phù hợp với" tinh thần "của LINQ, đó là để tránh tác dụng phụ. Đó là "điểm chống lại" làm tính năng này. Tất nhiên cũng có một lập luận ngân sách chống lại việc đó, cụ thể là chi phí cơ hội không làm một tính năng tốt hơn. Nhưng điểm chống lại là điểm chống lại, và không phải tất cả các điểm chống lại đều dựa trên chi phí. –

6

Trình biên dịch C# làm tốt hơn thế.

a + b + c được biên dịch thành String.Concat(a, b, c), là nhanh hơn hơn StringBuilder.
"a" + "b" được biên dịch trực tiếp thành "ab" (hữu ích cho nhiều dòng chữ).

Nơi duy nhất để sử dụng StringBuilder là khi ghép nối lặp lại trong vòng lặp; trình biên dịch không thể dễ dàng tối ưu hóa điều đó.

+0

Có thực sự nhanh hơn bất kể kích thước và số lượng các chuỗi được nối hay không? – Shredderroy

+3

Đó là * chính xác * những gì câu hỏi đang nói về, mặc dù: ghép nối trong một vòng lặp. –

+1

@CodyGray: Tôi thấy khó tin rằng Java tối ưu hóa điều đó. – SLaks

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