13

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 メソッドがこのように記述されている理由を理解するのに苦労しています。範囲外のインデックスは、常に例外が発生するか、常に空の文字列になると予想されます。洞察はありますか?

4

4 に答える 4

15

の内部実装String.Substring(startindex)は次のようになります

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

したがって、長さがゼロ文字の文字列を要求しています。(別名String.Empty)これはMS側では明確ではないことには同意しますが、より適切な説明がなければ、例外をスローするよりもこの結果を出す方が良いと思います。

実装をさらに深く掘り下げると、String.Substring(startIndex, length)このコードが表示されます

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

したがって、length = 0は2番目のオーバーロードで有効な入力であるため、最初のオーバーロードでもその結果が得られます。

于 2012-07-28T22:33:45.857 に答える
3

.Net-Substring のドキュメントには、「123」が 3 の場合に、インデックスが文字列の長さよりも大きい場合に例外がスローされることが明確に記載されています。

その理由は、C++ 部分文字列関数と同じ動作を作成するための互換性のためかもしれません。C++ では、

test.substr(3)

NULL 終端のため、空の文字列が返されます。つまり、文字列 "123" には実際には 4 文字が含まれています。(最後のものは \0 です)。

仕様ごとの.Netにnullで終わる文字列がなくても(実装には実際にはありますが...)、これはおそらくこの動作を行うための意図です。

于 2012-07-28T22:38:56.853 に答える
1

この実装が提供する便利さの 1 つは、任意の文字列に対して何かを実行する (たとえば、文字列の後半を返す) ループがある場合、空の文字列を特別なケースとして処理する必要がないことです。

于 2012-07-28T22:25:55.413 に答える
1

理由はわかりませんが、部分文字列呼び出しが文字列の最後にあるかどうかを確認したい場合は、 string.Empty を返す方が例外をスローするよりも安価です。

また、インデックス付きの文字の後の文字列の部分が空白になることを求めているだけだと思いますが、その後のインデックスは本当に範囲外です

于 2012-07-28T22:26:10.267 に答える