2009-08-31 31 views
17

Tôi hiểu rằng tôi có thể gọi ToString(). IndexOf (...), nhưng tôi không muốn tạo thêm chuỗi. Tôi hiểu rằng tôi có thể viết thủ tục tìm kiếm theo cách thủ công. Tôi tự hỏi tại sao một thói quen như vậy không tồn tại trong khuôn khổ.Tại sao StringBuilder không có phương thức IndexOf?

Trả lời

5

Thật không may, nhiều phương pháp được triển khai cho chuỗi có thể đã được triển khai cho StringBuilder nhưng điều đó không được thực hiện. Xem xét sử dụng các phương pháp mở rộng để thêm những gì bạn quan tâm.

1

Gọi ToString() trên StringBuilder không tạo thêm đối tượng, gây nhầm lẫn. Bên trong, StringBuilder lưu trữ đối tượng Chuỗi, để thực hiện; gọi ToString() chỉ cần trả về đối tượng đó.

+0

điều này không đúng trong ngữ cảnh của câu hỏi nếu người xây dựng chuỗi được yêu cầu sửa đổi chính nó Tthen a * new * string được tạo, khả năng thay đổi của bộ đệm bên trong không được hiển thị với mã được quản lý. – ShuggyCoUk

+0

@ ShuggyCoUk: bình luận của tôi là một chút glib. Tôi đã xóa nó. –

+10

Để làm rõ các bình luận trước, không có nhiều chi phí từ việc gọi ToString. Nhưng sau khi bạn gọi nó, sửa đổi tiếp theo cho StringBuilder sẽ phải chịu phí sao chép. (Đây là một sự tối ưu hợp lệ vì ToString thường là điều cuối cùng được thực hiện cho một StringBuilder.) Kết quả là, việc triển khai hiệu quả các phương thức giống như String không thể sử dụng ToString, mà ngăn cản một giải pháp nhỏ cho vấn đề của poster ban đầu. –

36

Tôi biết đây là câu hỏi cũ, tuy nhiên tôi đã viết phương pháp tiện ích thực hiện một số IndexOf trên StringBuilder. Nó là dưới đây. Tôi hy vọng nó sẽ giúp bất kỳ ai tìm thấy câu hỏi này, hoặc từ một tìm kiếm Google hoặc tìm kiếm StackOverflow.

/// <summary> 
/// Returns the index of the start of the contents in a StringBuilder 
/// </summary>   
/// <param name="value">The string to find</param> 
/// <param name="startIndex">The starting index.</param> 
/// <param name="ignoreCase">if set to <c>true</c> it will ignore case</param> 
/// <returns></returns> 
public static int IndexOf(this StringBuilder sb, string value, int startIndex, bool ignoreCase) 
{    
    int index; 
    int length = value.Length; 
    int maxSearchLength = (sb.Length - length) + 1; 

    if (ignoreCase) 
    { 
     for (int i = startIndex; i < maxSearchLength; ++i) 
     { 
      if (Char.ToLower(sb[i]) == Char.ToLower(value[0])) 
      { 
       index = 1; 
       while ((index < length) && (Char.ToLower(sb[i + index]) == Char.ToLower(value[index]))) 
        ++index; 

       if (index == length) 
        return i; 
      } 
     } 

     return -1; 
    } 

    for (int i = startIndex; i < maxSearchLength; ++i) 
    { 
     if (sb[i] == value[0]) 
     { 
      index = 1; 
      while ((index < length) && (sb[i + index] == value[index])) 
       ++index; 

      if (index == length) 
       return i; 
     } 
    } 

    return -1; 
} 
+1

Người ta nói [Sử dụng phương thức String.ToUpperInvariant thay vì phương thức String.ToLowerInvariant khi bạn chuẩn hóa chuỗi để so sánh] (https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices -strings # đề xuất-cho-chuỗi-sử dụng). Tôi đoán điều này cũng đúng cho so sánh nhân vật: [Char.ToUpper và Char.ToLower hoạt động tương tự như các phương thức String.ToUpper và String.ToLower được mô tả trong phần trước] (https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings # biểu đồ và biểu đồ) – Sergey

+0

Cuộc gọi công bằng; cảm thấy tự do thực hiện chỉnh sửa cho bài đăng ở trên. – Dennis

+1

Xin lỗi, tôi đã sai. Trên thực tế Microsoft đã tối ưu hóa * ToUpperInvariant() *, không * ToUpper() *. Trong trường hợp này, chúng tôi không thể cung cấp * ToUpperInvariant() * theo mặc định cho đến khi nó có thể dẫn đến việc so sánh sai trong một số ngôn ngữ như tiếng Thổ Nhĩ Kỳ. Vì vậy, về vấn đề này, mã của bạn là hoàn toàn chính xác. – Sergey

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