Подтвердить что ты не робот

Удивительное поведение подстроки

Я столкнулся с этим поведением сегодня, используя метод 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] оба находятся за пределами границ. Это задокументировано в MSDN, но мне трудно понять, почему метод Substring написан таким образом. Я ожидаю, что любой индекс вне пределов всегда будет приводить к исключению или всегда приводит к пустой строке. Любое понимание?

4b9b3361

Ответ 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.

Я предполагаю, что причина может быть из-за совместимости, чтобы создать то же поведение, что и подстрочная функция С++. В С++,

test.substr(3)

возвращает пустую строку из-за NULL-завершения, что означает, что строка "123" фактически содержит 4 символа! (последний из которых равен 0).

Вероятно, это намерение иметь такое поведение, даже если .Net в спецификации не имеет строк с нулевым завершением (хотя реализация фактически делает...)

Ответ 3

Единственное удобство, которое обеспечивает эта реализация, состоит в том, что если бы у вас был цикл, который делал что-то с некоторыми произвольными строками (например, возвращая вторую половину строки), вам не пришлось бы обрабатывать пустую строку как специальную случай.

Ответ 4

Не знаю, почему, не могу представить себе причину, почему, но я полагаю, если вы хотите проверить, находится ли подстрочный вызов в конце строки, возвращая string.Empty дешевле, чем бросать исключение.

Также я предполагаю, что вы просто запрашиваете часть строки после индексированного символа, который будет пустым, тогда как индекс после этого действительно выходит за пределы диапазона