【问题标题】:Surprising Substring behavior令人惊讶的子字符串行为
【发布时间】:2012-07-27 03:29:35
【问题描述】:

我今天在使用 Substring 方法时遇到了这种行为:

static void Main(string[] args) {
    string test = "123";
    for (int i = 0; true; i++) {
        try {
            Console.WriteLine("\"{0}\".Substring({1}) is \"{2}\"", test, i, test.Substring(i));
        } catch (ArgumentOutOfRangeException e) {
            Console.WriteLine("\"{0}\".Substring({1}) threw an exception.", test, i);
                break;
        }
    }
}

输出:

"123".Substring(0) is "123"
"123".Substring(1) is "23"
"123".Substring(2) is "3"
"123".Substring(3) is ""
"123".Substring(4) threw an exception.

"123".Substring(3) 返回空字符串,"123".Substring(4) 抛出异常。但是,“123”[3] 和“123”[4] 都超出了范围。这是documented on MSDN,但我很难理解为什么 Substring 方法是这样写的。我希望任何越界索引要么总是导致异常,要么总是导致空字符串。有什么见解吗?

【问题讨论】:

  • 你的问题是为什么 Substring(3) 会返回不同的结果给 Substring(4)?
  • 抱歉,这里的越界索引在哪里?
  • Daniel:test.Substring(3) 和 test.Substring(4) 都提供越界索引,但它们的行为不同。
  • SubString(3) 仅在您期望(要求)非空结果时才超出范围。

标签: c# string


【解决方案1】:

String.Substring(startindex)的内部实现是这样的

public string Substring(int startIndex)
{
    return this.Substring(startIndex, this.Length - startIndex);
}

所以你要求一个零字符长度的字符串。 (A.K.A. String.Empty) 我同意你的观点,这在 MS 部分并不清楚,但没有更好的解释,我认为给出这个结果比抛出异常更好。

更深入地实现String.Substring(startIndex, length),我们看到了这段代码

if (length == 0)
{
    return Empty;
}

因此,由于 length=0 在第二个重载中是一个有效输入,所以我们也为第一个重载得到该结果。

【讨论】:

    【解决方案2】:

    .Net-Substring 的文档明确指出,如果索引大于字符串的长度,则抛出异常,在“123”为 3 的情况下。

    我猜原因可能是因为兼容性,要创建与 C++ 子字符串函数相同的行为。在 C++ 中,

    test.substr(3)
    

    由于 NULL 终止,将返回一个空字符串,这意味着字符串“123”实际上包含 4 个字符! (最后一个是\0)。

    这可能是产生这种行为的意图,即使 .Net 每个规范没有以 null 结尾的字符串(尽管实现实际上有......)

    【讨论】:

      【解决方案3】:

      此实现提供的一个便利是,如果您有一个循环对一些任意字符串执行某些操作(例如,返回字符串的后半部分),您不必将空字符串作为特殊字符串处理案例。

      【讨论】:

        【解决方案4】:

        不知道为什么,也想不出一个很好的理由,但我想如果你想检查一个子字符串调用是否在一个字符串的末尾,返回 string.Empty 比抛出异常更便宜。

        另外我想你只是要求在索引字符之后的字符串部分是空白的,而之后的索引确实超出范围

        【讨论】:

          猜你喜欢
          • 2019-10-05
          • 1970-01-01
          • 2021-08-20
          • 1970-01-01
          • 1970-01-01
          • 2016-12-19
          • 1970-01-01
          • 2015-10-19
          • 2012-08-11
          相关资源
          最近更新 更多