Tengo un código y cuando se ejecuta, arroja un mensaje que IndexOutOfRangeException
dice:
El índice esta fuera de los límites de la matriz.
¿Qué significa esto y qué puedo hacer al respecto?
Dependiendo de las clases utilizadas, también puede ser ArgumentOutOfRangeException
Se produjo una excepción del tipo 'System.ArgumentOutOfRangeException' en mscorlib.dll pero no se manejó en el código de usuario Información adicional: El índice estaba fuera de rango. Debe ser no negativo y menor que el tamaño de la colección.
Esta excepción significa que está intentando acceder a un elemento de la colección por índice, utilizando un índice no válido. Un índice no es válido cuando es menor que el límite inferior de la colección o mayor o igual al número de elementos que contiene.
Dada una matriz declarada como:
byte[] array = new byte[4];
Puede acceder a esta matriz de 0 a 3, los valores fuera de este rango harán IndexOutOfRangeException
que se arrojen. Recuerde esto cuando cree y acceda a una matriz.
Longitud de la matriz
En C #, normalmente, las matrices están basadas en 0. Significa que el primer elemento tiene índice 0 y el último elemento tiene índice Length - 1
(donde Length
es el número total de elementos en la matriz) por lo que este código no funciona:
array[array.Length] = 0;
Además, tenga en cuenta que si tiene una matriz multidimensional, entonces no puede usar Array.Length
para ambas dimensiones, debe usar Array.GetLength()
:
int[,] data = new int[10, 5];
for (int i=0; i < data.GetLength(0); ++i) {
for (int j=0; j < data.GetLength(1); ++j) {
data[i, j] = 1;
}
}
El límite superior no es inclusivo
En el siguiente ejemplo, creamos una matriz bidimensional sin procesar de Color
. Cada elemento representa un píxel, los índices son de (0, 0)
a (imageWidth - 1, imageHeight - 1)
.
Color[,] pixels = new Color[imageWidth, imageHeight];
for (int x = 0; x <= imageWidth; ++x) {
for (int y = 0; y <= imageHeight; ++y) {
pixels[x, y] = backgroundColor;
}
}
Este código fallará porque la matriz está basada en 0 y el último píxel (inferior derecho) de la imagen es pixels[imageWidth - 1, imageHeight - 1]
:
pixels[imageWidth, imageHeight] = Color.Black;
En otro escenario, puede obtener ArgumentOutOfRangeException
este código (por ejemplo, si está usando un GetPixel
método en una Bitmap
clase).
Las matrices no crecen
Una matriz es rápida. Muy rápido en la búsqueda lineal en comparación con cualquier otra colección. Esto se debe a que los elementos son contiguos en la memoria, por lo que la dirección de la memoria se puede calcular (y el incremento es solo una adición). No es necesario seguir una lista de nodos, ¡matemáticas simples! Usted paga esto con una limitación: no pueden crecer, si necesita más elementos, necesita reasignar esa matriz (esto puede llevar un tiempo relativamente largo si los elementos antiguos deben copiarse en un nuevo bloque). Los redimensiona con Array.Resize<T>()
, este ejemplo agrega una nueva entrada a una matriz existente:
Array.Resize(ref array, array.Length + 1);
No olvide que los índices válidos son de 0
a Length - 1
. Si simplemente intenta asignar un elemento Length
, obtendrá IndexOutOfRangeException
(este comportamiento puede confundirlo si cree que pueden aumentar con una sintaxis similar al Insert
método de otras colecciones).
Matrices especiales con límite inferior personalizado El
primer elemento de las matrices siempre tiene el índice 0 . Esto no siempre es cierto porque puede crear una matriz con un límite inferior personalizado:
var array = Array.CreateInstance(typeof(byte), new int[] { 4 }, new int[] { 1 });
En ese ejemplo, los índices de matriz son válidos de 1 a 4. Por supuesto, el límite superior no se puede cambiar.
Argumentos incorrectos
Si accede a una matriz utilizando argumentos no validados (de la entrada del usuario o de la función del usuario), puede obtener este error:
private static string[] RomanNumbers =
new string[] { "I", "II", "III", "IV", "V" };
public static string Romanize(int number)
{
return RomanNumbers[number];
}
Resultados inesperados
Esta excepción también puede producirse por otra razón: por convención, muchas funciones de búsqueda devolverán -1 (nullables se introdujeron con .NET 2.0 y de todos modos también es una convención bien conocida en uso desde hace muchos años) si no lo hicieron ' No encuentro nada. Imaginemos que tiene una matriz de objetos comparable con una cadena. Puede pensar en escribir este código:
// Items comparable with a string
Console.WriteLine("First item equals to 'Debug' is '{0}'.",
myArray[Array.IndexOf(myArray, "Debug")]);
// Arbitrary objects
Console.WriteLine("First item equals to 'Debug' is '{0}'.",
myArray[Array.FindIndex(myArray, x => x.Type == "Debug")]);
Esto fallará si ningún elemento myArray
satisface la condición de búsqueda porque Array.IndexOf()
devolverá -1 y luego se lanzará el acceso a la matriz.
El siguiente ejemplo es un ejemplo ingenuo para calcular las ocurrencias de un conjunto dado de números (conocer el número máximo y devolver una matriz donde el elemento en el índice 0 representa el número 0, los elementos en el índice 1 representan el número 1 y así sucesivamente):
static int[] CountOccurences(int maximum, IEnumerable<int> numbers) {
int[] result = new int[maximum + 1]; // Includes 0
foreach (int number in numbers)
++result[number];
return result;
}
Por supuesto, es una implementación bastante terrible, pero lo que quiero mostrar es que fallará para los números negativos y los números anteriores maximum
.
¿Cómo se aplica a List<T>
?
Los mismos casos que arreglo - rango de índices válidos - 0 ( List
los índices siempre comienzan con 0) para list.Count
- acceder a elementos fuera de este rango causará la excepción.
Tenga en cuenta que se List<T>
lanza ArgumentOutOfRangeException
para los mismos casos en los que se utilizan matrices IndexOutOfRangeException
.
A diferencia de las matrices, List<T>
comienza vacío, por lo que intentar acceder a elementos de la lista recién creada conduce a esta excepción.
var list = new List<int>();
El caso común es llenar la lista con indexación (similar a Dictionary<int, T>
) causará una excepción:
list[0] = 42; // exception
list.Add(42); // correct
IDataReader y Columns
Imagine que está intentando leer datos de una base de datos con este código:
using (var connection = CreateConnection()) {
using (var command = connection.CreateCommand()) {
command.CommandText = "SELECT MyColumn1, MyColumn2 FROM MyTable";
using (var reader = command.ExecuteReader()) {
while (reader.Read()) {
ProcessData(reader.GetString(2)); // Throws!
}
}
}
}
GetString()
arrojará IndexOutOfRangeException
porque su conjunto de datos tiene solo dos columnas, pero está tratando de obtener un valor de la tercera (los índices siempre se basan en 0).
Tenga en cuenta que este comportamiento se comparte con la mayoría de las IDataReader
implementaciones ( SqlDataReader
, OleDbDataReader
y así sucesivamente).
También puede obtener la misma excepción si usa la sobrecarga IDataReader del operador indexador que toma un nombre de columna y pasa un nombre de columna no válido.
Supongamos, por ejemplo, que ha recuperado una columna denominada Columna1 pero luego intenta recuperar el valor de ese campo con
var data = dr["Colum1"]; // Missing the n in Column1.
Esto sucede porque el operador indexador se implementa al intentar recuperar el índice de un campo Colum1 que no existe. El método GetOrdinal lanzará esta excepción cuando su código auxiliar interno devuelva un -1 como índice de "Colum1".
Otros
Hay otro caso (documentado) cuando se lanza esta excepción: si, en DataView
, el nombre de la columna de datos que se proporciona a la DataViewSort
propiedad no es válido.
En este ejemplo, déjame suponer, por simplicidad, que las matrices son siempre monodimensionales y basadas en 0. Si desea ser estricto (o está desarrollando una biblioteca), es posible que deba reemplazar 0
con GetLowerBound(0)
y .Length
con GetUpperBound(0)
(por supuesto, si tiene parámetros de tipo System.Arra
y, no se aplica T[]
). Tenga en cuenta que en este caso, el límite superior es inclusivo y luego este código:
for (int i=0; i < array.Length; ++i) { }
Debería reescribirse así:
for (int i=array.GetLowerBound(0); i <= array.GetUpperBound(0); ++i) { }
Tenga en cuenta que esto no está permitido (arrojará InvalidCastException
), por eso, si sus parámetros son T[]
, está seguro sobre las matrices personalizadas de límite inferior:
void foo<T>(T[] array) { }
void test() {
// This will throw InvalidCastException, cannot convert Int32[] to Int32[*]
foo((int)Array.CreateInstance(typeof(int), new int[] { 1 }, new int[] { 1 }));
}
Validar parámetros
Si el índice proviene de un parámetro, siempre debe validarlo (arrojando apropiado ArgumentException
o ArgumentOutOfRangeException
). En el siguiente ejemplo, los parámetros incorrectos pueden causar IndexOutOfRangeException
, los usuarios de esta función pueden esperar esto porque están pasando una matriz, pero no siempre es tan obvio. Sugeriría validar siempre los parámetros para las funciones públicas:
static void SetRange<T>(T[] array, int from, int length, Func<i, T> function)
{
if (from < 0 || from>= array.Length)
throw new ArgumentOutOfRangeException("from");
if (length < 0)
throw new ArgumentOutOfRangeException("length");
if (from + length > array.Length)
throw new ArgumentException("...");
for (int i=from; i < from + length; ++i)
array[i] = function(i);
}
Si la función es privada, simplemente puede reemplazar la if
lógica con Debug.Assert()
:
Debug.Assert(from >= 0 && from < array.Length);
Es
posible que el índice Check Object State Array no provenga directamente de un parámetro. Puede ser parte del estado del objeto. En general, siempre es una buena práctica validar el estado del objeto (por sí mismo y con parámetros de función, si es necesario). Puede usar Debug.Assert()
, lanzar una excepción adecuada (más descriptiva sobre el problema) o manejar eso como en este ejemplo:
class Table {
public int SelectedIndex { get; set; }
public Row[] Rows { get; set; }
public Row SelectedRow {
get {
if (Rows == null)
throw new InvalidOperationException("...");
// No or wrong selection, here we just return null for
// this case (it may be the reason we use this property
// instead of direct access)
if (SelectedIndex < 0 || SelectedIndex >= Rows.Length)
return null;
return Rows[SelectedIndex];
}
}
Validar valores devueltos
En uno de los ejemplos anteriores usamos directamente el Array.IndexOf()
valor devuelto. Si sabemos que puede fallar, entonces es mejor manejar ese caso:
int index = myArray[Array.IndexOf(myArray, "Debug");
if (index != -1) { } else { }
En mi opinión, la mayoría de las preguntas, aquí en SO, sobre este error pueden simplemente evitarse. El tiempo que dedica a escribir una pregunta adecuada (con un pequeño ejemplo de trabajo y una pequeña explicación) fácilmente podría ser mucho más que el tiempo que necesitará para depurar su código. En primer lugar, lea esta publicación del blog de Eric Lippert sobre la depuración de programas pequeños , no repetiré sus palabras aquí, pero es absolutamente imprescindible .
Tiene código fuente, tiene un mensaje de excepción con un seguimiento de pila. Vaya allí, elija el número de la línea derecha y verá:
array[index] = newValue;
Encontraste tu error, comprueba cómo index
aumenta. ¿Es correcto? Compruebe cómo se asigna la matriz, ¿es coherente con cómo index
aumenta? ¿Está bien de acuerdo con sus especificaciones? Si responde afirmativamente a todas estas preguntas, encontrará una buena ayuda aquí en StackOverflow, pero primero compruébelo usted mismo. ¡Ahorrará su propio tiempo!
Un buen punto de partida es utilizar siempre afirmaciones y validar las entradas. Es posible que incluso desee utilizar contratos de código. Cuando algo salió mal y no puedes averiguar qué sucede con un vistazo rápido a tu código, entonces tienes que recurrir a un viejo amigo: el depurador . Simplemente ejecute su aplicación en depuración dentro de Visual Studio (o su IDE favorito), verá exactamente qué línea arroja esta excepción, qué matriz está involucrada y qué índice está tratando de usar. Realmente, el 99% de las veces lo resolverás tú solo en unos minutos.
Si esto sucede en producción, es mejor que agregue afirmaciones en el código incriminado, probablemente no veremos en su código lo que no puede ver por sí mismo (pero siempre puede apostar).
Todo lo que hemos dicho en la respuesta de C # es válido para VB.NET con las obvias diferencias de sintaxis, pero hay un punto importante a considerar cuando se trata de matrices VB.NET.
En VB.NET, las matrices se declaran estableciendo el valor de índice válido máximo para la matriz. No es el recuento de los elementos que queremos almacenar en la matriz.
' declares an array with space for 5 integer
' 4 is the maximum valid index starting from 0 to 4
Dim myArray(4) as Integer
Entonces este bucle llenará la matriz con 5 enteros sin causar ninguna excepción IndexOutOfRangeException
For i As Integer = 0 To 4
myArray(i) = i
Next
Esta excepción significa que está intentando acceder a un elemento de colección por índice, utilizando un índice no válido. Un índice no es válido cuando es menor que el límite inferior de la colección o mayor queigual al número de elementos que contiene. el índice máximo permitido definido en la declaración de la matriz
Explicación simple sobre qué es una excepción de índice fuera de límite:
Solo piense que hay un tren allí, sus compartimentos son D1, D2, D3. Un pasajero vino a entrar al tren y tiene el boleto de D4. ahora que va a pasar. el pasajero quiere entrar en un compartimento que no existe por lo que obviamente surgirá un problema.
Mismo escenario: siempre que intentamos acceder a una lista de matrices, etc., solo podemos acceder a los índices existentes en la matriz. array[0]
y array[1]
existen. Si intentamos acceder array[3]
, en realidad no está allí, por lo que surgirá una excepción de índice fuera del límite.
Para comprender fácilmente el problema, imagine que escribimos este código:
static void Main(string[] args)
{
string[] test = new string[3];
test[0]= "hello1";
test[1]= "hello2";
test[2]= "hello3";
for (int i = 0; i <= 3; i++)
{
Console.WriteLine(test[i].ToString());
}
}
El resultado será:
hello1
hello2
hello3
Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
El tamaño de la matriz es 3 (índices 0, 1 y 2), pero el bucle for se repite 4 veces (0, 1, 2 y 3).
Entonces, cuando intenta acceder fuera de los límites con (3) lanza la excepción.
Aparte de la respuesta aceptada completa muy larga, hay un punto importante que hacer en IndexOutOfRangeException
comparación con muchos otros tipos de excepciones, y es:
A menudo hay un estado de programa complejo sobre el que puede ser difícil tener control en un punto particular del código, por ejemplo, una conexión de base de datos falla, por lo que los datos de una entrada no se pueden recuperar, etc.Este tipo de problema a menudo da como resultado una excepción de algún tipo que tiene que subir a un nivel superior porque donde ocurre no tiene forma de lidiar con eso en ese punto.
IndexOutOfRangeException
es generalmente diferente en que en la mayoría de los casos es bastante trivial verificar en el punto donde se genera la excepción. Generalmente, este tipo de excepción es lanzada por algún código que podría resolver fácilmente el problema en el lugar en el que ocurre, simplemente verificando la longitud real de la matriz. No desea 'arreglar' esto manejando esta excepción más arriba, sino asegurándose de que no se produzca en la primera instancia, lo que en la mayoría de los casos es fácil de hacer al verificar la longitud de la matriz.
Otra forma de expresar esto es que pueden surgir otras excepciones debido a una falta genuina de control sobre la entrada o el estado del programa, PERO la IndexOutOfRangeException
mayoría de las veces es simplemente un error piloto (programador).
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.
Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.
¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.