>
>
>
V3186. The arguments violate the bounds…


V3186. The arguments violate the bounds of collection. Passing these values into the method will result in an exception.

The analyzer has detected a suspicious method call that performs operations on a collection fragment. The arguments passed to the method are incorrect — they violate the bounds of the collection. As a result, an exception is thrown.

Consider an example:

int[] arr = new int[] { 0, 1, 3, 4 };
var indexOfOdd = Array.FindIndex(arr, 
                                 startIndex: 2,
                                 count: 3, 
                                 x => x % 2 == 1);

The 'FindIndex' method gets the following arguments:

  • 'arr' is an array where an element index will be searched;
  • 'startIndex: 2' is an element from which the search starts;
  • 'count: 3' is a number of items to be iterated, starting from 'startIndex: 2';
  • 'x => x %2 == 1' is a predicate containing a condition to compare the element.

The method returns either the index of the first element where the predicate is true, or '-1'.

The 'arr' array consists of four elements, so the index of the last element is '3'. The developer is trying to access the element with the '4' index. In this case, the corresponding exception will be thrown.

The correct implementation of the element index search may look as follows:

int[] arr = new int[] { 0, 1, 3, 4 };
var indexOfOdd = Array.FindIndex(arr, 
                                 startIndex: 2,
                                 count: 2, 
                                 x => x % 2 == 1);

Alternatively, you can use the method overloading that does not specify the 'count' parameter. In this case, the iteration will always end at the last element of the collection:

int[] arr = new int[] { 0, 1, 3, 4 };
var indexOfOdd = Array.FindIndex(arr, 
                                 startIndex: 2,
                                 x => x % 2 == 1);

Also, we can iterate the collection in reverse order. For example:

int[] arr = new int[] { 0, 1, 3, 4 };
var lastEvenInd = Array.FindLastIndex(arr,
                                      startIndex: 1,
                                      count: 3,
                                      x => x % 2 == 0);

Here the arguments perform the same roles, but the elements will be iterated in reverse order. The search area is formed from an element with the '1' index and two preceding elements. Thus, the method will need to access the '-1' index. Since this behavior is incorrect, an exception will be thrown.

In this case, the correct implementation of the index search may look as follows:

int[] arr = new int[] { 0, 1, 3, 4 };
var lastEvenInd = Array.FindLastIndex(arr,
                                      startIndex: 1,
                                      count: 2,
                                      x => x % 2 == 0);

Let's consider a more complex example:

var list = new List<int> { 2, 3, 5, 7 };
var index = GetFirstEvenIndex(list, 1, list.Count);
....
public int GetFirstEvenIndex(List<int> lst, int startIndex, int count)
{
  return lst.FindIndex(startIndex, count, x => x % 2 == 0);
}

Here are the parameters of the 'GetFirstEvenIndex' method:

  • 'lst' is a collection where the index of the first even number in the specified range is searched;
  • 'startIndex' is an element from which the search starts;
  • 'count' is a number of elements in the processed range.

Here the search range is formed from the element with the '1' index to the element with the 'list.Count' index inclusive. Thus, the method will need to access the index placed out of bounds. Since this behavior is incorrect, an exception will be thrown.

The correct code for passing arguments to the method may look as follows:

var list = new List<int> { 2, 3, 5, 7 };
var startIndex = 1;
var index = GetFirstEvenIndex(list, startIndex, list.Count - startIndex);

This diagnostic is classified as: