Reputation: 241
At some point in my code, I use this method:
IndexOf(string str, int startIndex)
I am also doing some calculations before, and I invoke this method with second argument (startIndex) equal to length of a string passed as first argument. Of course, no such an index exists in a string, and if we did something like this:
string[string.Length]
we would get an IndexOutOfRangeException
How does that method work exactly? In MSDN documentation it is clearly said, that startIndex is zero-based index of a string. Does it work and doesn't throw because a char array that String
class operates on is null-terminated?
I want to make sure that my program won't throw at any point.
Upvotes: 2
Views: 3053
Reputation: 152521
From the documentation:
If startIndex equals the length of the string instance, the method returns -1.
As to why it doesn't throw an exception if index==length
like array accessors do, the framework designers would have to answer that since the documentation doesn't say, and the C# source code eventually calls an internal C function.. Some uneducated guesses:
Upvotes: 2
Reputation: 387607
public unsafe int IndexOf(char value, int startIndex, int count) {
if (startIndex < 0 || startIndex > Length)
throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index"));
if (count < 0 || count > Length - startIndex)
throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count"));
fixed (char* pChars = &m_firstChar)
{
char* pCh = pChars + startIndex;
while (count >= 4)
{
// .. some search
}
while (count > 0)
{
// .. some search
}
}
return -1;
}
As you can see, the ArgumentOutOfRangeException
is only thrown when using a startIndex
that is larger than the length of the string. Since you are passing the length itself, this is not a problem. If you were to pass a number larger than it, you would see the exception:
Console.WriteLine("foo".IndexOf('a', 3)); // -1
Console.WriteLine("foo".IndexOf('a', 4)); // throws ArgumentOutOfRangeException
Now, we’re not actually calling the IndexOf
shown above. Instead we are calling the following signature:
public int IndexOf(char value, int startIndex) {
return IndexOf(value, startIndex, this.Length - startIndex);
}
So for the count
parameter above, the value this.Length - startIndex
is passed. Since startIndex
is equal to the length, count
will be zero.
So the two while loops we see in the implementation above will not execute at all. And thus, the default result -1
is returned.
(Small note: I’m using the .NET Core source since the .NET Framework reference source does not include the source of this method. The implementations should be mostly identical though.)
As for why you can begin your search after the end of the string, I have a simple explanation that could be the reason. If you look at a string, you can start searching at multiple points. Let’s use "foo bar"
as the string:
Index: 0 1 2 3 4 5 6
Character: f o o b a r
Points: ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
0 1 2 3 4 5 6 7
As you can see, there are 8 points before or after a character for a string of length 7. When you specify things like a start index, you aren’t actually talking about the character index, but the point index of the space in between the characters. This is evident by a use of "foo bar".Substring(5, 1)
where you get the characters between point 5 and point 6 (5+1). This is also why str.Substring(str.Length)
is an actually logical use to get the empty string that’s at the end of the string.
Upvotes: 3
Reputation: 35270
MSDN clearly states what exceptions it can throw. For example:
ArgumentOutOfRangeException
startIndex is less than 0 (zero) or greater than the length of this string.
It goes on to say:
Index numbering starts from 0. The startIndex parameter can range from 0 to the length of the string instance. If startIndex equals the length of the string instance, the method returns -1.
So there's really no guesswork required regarding exceptions.
Upvotes: 2
Reputation: 460098
It's mentioned explicitly in the documentation:
Index numbering starts from 0. The startIndex parameter can range from 0 to the length of the string instance. If startIndex equals the length of the string instance, the method returns -1.
Upvotes: 5