这段代码如何可能:“ArgumentOutOfRangeException:startIndex不能大于字符串的长度”?

问题描述:

我在我的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

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 字符集包括可忽略字符,这是执行语言或文化敏感比较时不被视为字符。在对文化敏感的搜索中,如果值包含可忽略的字符,则结果等同于使用删除的字符进行搜索。 ... –

的意见后,我发现了子无效指数不会失败。真正的问题是

@string.IndexOf(substring); 

由皮埃尔 - 吕克Pineault指出

更正:

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

ABCDEF和EF正确返回ABCD。您是否尝试运行代码? –

+0

你说得对。我只是测试了代码,并注意到子字符串在这种情况下是宽容的。 –