2013-07-21 40 views
17

tôi có phương pháp sau đây trong mã của tôi # C:Làm thế nào có thể trong mã này: "ArgumentOutOfRangeException: startIndex không thể lớn hơn chiều dài chuỗi"?

/// <summary> 
/// Removes the first (leftmost) occurence of a <paramref name="substring"/> from a <paramref name="string"/>. 
/// </summary> 
/// <param name="string">The string to remove the <paramref name="substring"/> from. Cannot be <c>null</c>.</param> 
/// <param name="substring">The substring to look for and remove from the <paramref name="string"/>. Cannot be <c>null</c>.</param> 
/// <returns> 
/// The rest of the <paramref name="string"/>, after the first (leftmost) occurence of the <paramref name="substring"/> in it (if any) has been removed. 
/// </returns> 
/// <remarks> 
/// <list type="bullet"> 
/// <item>If the <paramref name="substring"/> does not occur within the <paramref name="string"/>, the <paramref name="string"/> is returned intact.</item> 
/// <item>If the <paramref name="substring"/> has exactly one occurence within the <paramref name="string"/>, that occurence is removed, and the rest of the <paramref name="string"/> is returned.</item> 
/// <item>If the <paramref name="substring"/> has several occurences within the <paramref name="substring"/>, the first (leftmost) occurence is removed, and the rest of the <paramref name="string"/> is returned.</item> 
/// </list> 
/// </remarks> 
/// <exception cref="ArgumentNullException"> 
/// The <paramref name="string"/> is <c>null</c>. -or- The <paramref name="substring"/> is <c>null</c>. 
/// </exception> 
public static string RemoveSubstring(string @string, string substring) 
{ 
    if (@string == null) 
     throw new ArgumentNullException("string"); 

    if (substring == null) 
     throw new ArgumentNullException("substring"); 

    var index = @string.IndexOf(substring); 
    return index == -1 
     ? @string 
     : @string.Substring(0, index) + @string.Substring(index + substring.Length); 
} 

Việc thực hiện trông rất đơn giản và rõ ràng, và có một phạm vi tuyệt vời bằng cách kiểm tra đơn vị. Không có kết quả bất ngờ nào xảy ra trên máy của tôi, xây dựng máy chủ hoặc bất kỳ máy nào khác mà tôi có quyền truy cập hoặc trong hầu hết các môi trường sản xuất.

Trừ rằng chỉ có một khách hàng từ xa thỉnh thoảng báo cáo một vụ tai nạn ứng dụng tại phương pháp này với các vết đống sau:

System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. 
Parameter name: startIndex 
    at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) 
    at System.String.Substring(Int32 startIndex) 
    at MyNamespace.StringUtils.RemoveSubstring(String string, String substring) 
    at ... 

Thật không may, tôi không có một truy cập từ xa đến môi trường sản xuất này hoặc dữ liệu của nó, hoặc cho bất kỳ thông tin bổ sung nào. Đối với một số lý do, hiện tại tôi không thể triển khai hệ thống ghi nhật ký hoặc thu thập kết xuất sự cố ở đó.

Nhìn vào mã và thử kết hợp các đối số khác nhau, tôi không thể tưởng tượng được ngoại lệ này có thể xảy ra như thế nào.

Bạn có thể giúp tôi với một số ý tưởng không?

+0

Chỉ mụcOf là văn hóa cụ thể. Hãy xem các ví dụ tại đây (http://msdn.microsoft.com/en-us/library/ms224425.aspx) để xem cách chỉ mục có thể thay đổi. –

+0

Bạn có thể sử dụng phương thức String.Remove (Int32, Int32) tốt hơn. Bạn có thể thấy nó tha thứ hơn. ': @ string.Remove (index, substring.Length)' – tinstaafl

Trả lời

10
RemoveSubstring("A", "A\uFFFD"); // throws ArgumentOutOfRangeException 
RemoveSubstring("A", "A\u0640"); // throws ArgumentOutOfRangeException 

Nhiều chức năng cho chuỗi thao tác trong .NET, bao gồm IndexOf là văn hóa theo mặc định (thường có quá tải, nơi bạn có thể vượt qua StringComparison.Ordinal hoặc StringComparer.Ordinal để chuyển sang so sánh bitwise). Cá nhân, tôi không hài lòng với những gì đã được chọn là hành vi mặc định, nhưng đã quá muộn để làm bất cứ điều gì về nó, ngoại trừ có thể, thiết lập các nguyên tắc phát triển rõ ràng và các quy tắc FxCop.

Nhưng đôi khi hoạt động văn hóa cụ thể chính xác là những gì bạn cần. Thật không may, ngữ nghĩa của họ có thể phức tạp và phản trực giác, có thể vi phạm một số bất biến giả định bình thường, và có rất nhiều trường hợp góc để chăm sóc. Các nhà phát triển chịu trách nhiệm thực hiện một logic nhạy cảm về văn hóa trong một ứng dụng phải rất có trình độ trong lĩnh vực này và luôn hiểu chính xác những gì họ đang làm. Tôi khuyên bạn nên đặt tiêu chuẩn đánh giá và kiểm tra cho khu vực này ở trên mức bình thường.

+0

Bạn có thể thêm rằng anh ta có thể sửa chữa nó bằng cách thêm 'StringComparison.Ordinal' vào' IndexOf'. –

+1

Từ tài liệu: http://msdn.microsoft.com/en-us/library/k8b1470s.aspx Ký tự bao gồm các ký tự không thể bỏ qua, là các ký tự không được xem xét khi thực hiện so sánh ngôn ngữ hoặc văn hóa nhạy cảm.Trong tìm kiếm văn hóa nhạy cảm, nếu giá trị chứa ký tự không thể bỏ qua, kết quả tương đương với tìm kiếm với ký tự đó đã bị xóa. ... –

-1

Sau khi nhận xét, tôi phát hiện ra chuỗi con không thành công trên chỉ mục không hợp lệ. Vấn đề thực sự là với

@string.IndexOf(substring); 

như chỉ ra bởi Pierre-Luc Pineault

Correction:

@string.IndexOf(substring, StringComparison.Ordinal); 
+4

ABCDEF và EF trả về chính xác ABCD. Bạn đã thử chạy mã chưa? –

+0

Bạn nói đúng. Tôi chỉ kiểm tra mã và nhận thấy rằng chuỗi con được tha thứ trong kịch bản như vậy. –