Why does List<T>.IndexOf
allow out-of-range start index?
var list = new List<int>() { 100 };
Console.WriteLine(list.IndexOf(1/*item*/, 1/*start index*/));
There will not be any exceptions. But there is no item with 1
index in this collection! There is just one item with 0
index.
So, why does .Net
allow you to do it?
First of all, if someone should take care of an invalid input it's the runtime and not the compiler since the input is of the same valid type (int
).
With that said, actually, seeing the source code of IndexOf
making it seem like an implementation bug:
[__DynamicallyInvokable]
public int IndexOf(T item, int index)
{
if (index > this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
}
return Array.IndexOf<T>(this._items, item, index, this._size - index);
}
As you can see, it was intended to not allow you to insert an invalid index which is bigger than the size of the list, but the comparison is done with >
instead of >=
.
The following code returns 0
:
var list = new List<int>() { 100 };
Console.WriteLine(list.IndexOf(100/*item*/, 0/*start index*/));
The following code returns -1
:
var list = new List<int>() { 100 };
Console.WriteLine(list.IndexOf(100/*item*/, 1/*start index*/));
While The following code throws an Exception
:
var list = new List<int>() { 100 };
Console.WriteLine(list.IndexOf(100/*item*/, 2/*start index*/));
There is no reason what so ever for the second and third cases to behave differently which makes it seem as a bug in the implementation of IndexOf
.
Also, the documentation says:
ArgumentOutOfRangeException | index is outside the range of valid indexes for the
List<T>
.
Which as we have just seen is not what happening.
Note: the same behaviour happens with arrays:
int[] arr = { 100 };
//Output: 0
Console.WriteLine(Array.IndexOf(arr, 100/*item*/, 0/*start index*/));
//Output: -1
Console.WriteLine(Array.IndexOf(arr, 100/*item*/, 1/*start index*/));
//Throws ArgumentOutOfRangeException
Console.WriteLine(Array.IndexOf(arr, 100/*item*/, 2/*start index*/));
It allows it because someone decided this was OK, and that someone either wrote the spec or implemented the method.
It is also somewhat documented in List(T).IndexOf
Method:
0 (zero) is valid in an empty list.
(which I also take that Count
is a valid start index for any list)
Note that the same thing is documented, but slightly better documented, for Array.IndexOf
Method:
If
startIndex
equalsArray.Length
, the method returns -1. IfstartIndex
is greater thanArray.Length
, the method throws anArgumentOutOfRangeException
.
Let me clarify my answer here.
You're asking "Why does this method allow this input".
The only legal reason is "Because someone implemented the method so that it did".
Is it a bug? It may very well be. The documentation only says that 0 is legal start index for an empty list, it does not directly say that 1 is legal or not for a list with a single element in it. The exception documentation for the method seems to contradict this (as has been brought up in comments) which seems to be in favor of it being a bug.
But the only reason for "why does it do this" is that someone actually implemented the method that way. It may be a conscious choice, it may be a bug, it may be an oversight either in the code or in the documentation.
The only one that can tell which one it is would be the person or people that implemented this method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With