2013-07-21 76 views
17

我在我的C#代碼如下方法:這段代碼如何可能:「ArgumentOutOfRangeException:startIndex不能大於字符串的長度」?

/// <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); 
} 

的實現看起來很淺顯,並通過單元測試有一個出色的網絡覆蓋。在我的計算機,構建服務器或任何其他有權訪問的計算機上,或在大多數生產環境中,都沒有發生意外的結果。

除了只有一個遠程用戶偶爾在此方法具有以下堆棧跟蹤報告應用程序崩潰:

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 ... 

不幸的是,我沒有這樣的生產環境或將其數據的遠程訪問,或到任何額外的信息。出於某些原因,目前我無法在那裏部署日誌記錄系統或崩潰轉儲收集。在代碼

展望,並嘗試的參數不同的組合,我無法想象怎麼可能會出現此異常。

能否請你幫我的一些想法?

+0

的IndexOf是特定的文化。查看示例[此處](http://msdn.microsoft.com/zh-cn/library/ms224425.aspx),查看索引如何更改。 –

+0

使用String.Remove(Int32,Int32)方法可能會更好。你可能會發現它更寬容。 ':@ string.Remove(index,substring.Length)' – tinstaafl

回答

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

在.NET字符串處理許多功能,包括IndexOf是文化 - 默認情況下是特定的(通常有超載,您可以通過StringComparison.OrdinalStringComparer.Ordinal切換到按位比較)。就我個人而言,我對選擇默認行爲並不滿意,但對此做任何事情都爲時已晚,除非可能設定明確的開發指南和FxCop規則。

但有時特定文化的操作正是你需要的。不幸的是,它們的語義可能會非常棘手,違反直覺,會違反一些通常假定的不變量,並且有很多需要處理的角落案例。在應用程序中負責實施文化敏感邏輯的開發人員應該在這方面非常合格,並且始終明確他們在做什麼。我會建議設置超出正常範圍的評估和測試標準。

+0

您可能會補充說,他可以通過在'IndexOf'中添加'StringComparison.Ordinal'來修復它。 –

+1

從文檔:http://msdn.microsoft.com/en-us/library/k8b1470s.aspx 字符集包括可忽略字符,這是執行語言或文化敏感比較時不被視爲字符。在對文化敏感的搜索中,如果值包含可忽略的字符,則結果等同於使用刪除的字符進行搜索。 ... –

-1

的意見後,我發現了子無效指數不會失敗。真正的問題是

@string.IndexOf(substring); 

由皮埃爾 - 呂克Pineault指出

更正:

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

ABCDEF和EF正確返回ABCD。您是否嘗試運行代碼? –

+0

你說得對。我只是測試了代碼,並注意到子字符串在這種情況下是寬容的。 –

相關問題