Ich habe einen Code und wenn er ausgeführt wird, wirft er ein IndexOutOfRangeException
Sprichwort:
Index war außerhalb der Grenzen des Arrays.
Was bedeutet das und was kann ich dagegen tun?
Abhängig von den verwendeten Klassen kann es auch sein ArgumentOutOfRangeException
Eine Ausnahme vom Typ 'System.ArgumentOutOfRangeException' ist in mscorlib.dll aufgetreten, wurde jedoch nicht im Benutzercode behandelt. Zusätzliche Informationen: Der Index lag außerhalb des Bereichs. Muss nicht negativ sein und kleiner als die Größe der Sammlung.
c#
.net
indexoutofrangeexception
Adriano Repetti
quelle
quelle
Antworten:
Was ist es?
Diese Ausnahme bedeutet, dass Sie versuchen, mit einem ungültigen Index indexweise auf ein Sammlungselement zuzugreifen. Ein Index ist ungültig, wenn er niedriger als die Untergrenze der Sammlung oder größer oder gleich der Anzahl der darin enthaltenen Elemente ist.
Wenn es geworfen wird
Gegeben ein Array deklariert als:
Sie können von 0 bis 3 auf dieses Array zugreifen. Werte außerhalb dieses Bereichs
IndexOutOfRangeException
werden ausgelöst. Denken Sie daran, wenn Sie ein Array erstellen und darauf zugreifen.Array-Länge
In C # basieren Arrays normalerweise auf 0. Dies bedeutet, dass das erste Element den Index 0 und das letzte Element den Index hat
Length - 1
(wobeiLength
die Gesamtzahl der Elemente im Array angegeben ist), sodass dieser Code nicht funktioniert:Beachten Sie außerdem, dass Sie bei Verwendung eines mehrdimensionalen Arrays, das Sie nicht
Array.Length
für beide Dimensionen verwenden können, Folgendes verwenden müssenArray.GetLength()
:Obergrenze ist nicht inklusive Im folgenden Beispiel erstellen wir ein zweidimensionales Roharray von
Color
. Jedes Element stellt ein Pixel dar, die Indizes sind von(0, 0)
bis(imageWidth - 1, imageHeight - 1)
.Dieser Code schlägt dann fehl, da das Array auf 0 basiert und das letzte Pixel (unten rechts) im Bild wie folgt lautet
pixels[imageWidth - 1, imageHeight - 1]
:In einem anderen Szenario erhalten Sie möglicherweise
ArgumentOutOfRangeException
diesen Code (z. B. wenn Sie eineGetPixel
Methode für eineBitmap
Klasse verwenden).Arrays wachsen nicht
Ein Array ist schnell. Sehr schnell in der linearen Suche im Vergleich zu jeder anderen Sammlung. Dies liegt daran, dass Elemente im Speicher zusammenhängend sind, sodass die Speicheradresse berechnet werden kann (und das Inkrement nur eine Ergänzung ist). Keine Notwendigkeit, einer Knotenliste zu folgen, einfache Mathematik! Sie zahlen dies mit einer Einschränkung: Sie können nicht wachsen. Wenn Sie mehr Elemente benötigen, müssen Sie dieses Array neu zuweisen (dies kann relativ lange dauern, wenn alte Elemente in einen neuen Block kopiert werden müssen). Sie ändern die Größe mit
Array.Resize<T>()
. In diesem Beispiel wird einem vorhandenen Array ein neuer Eintrag hinzugefügt:Vergessen Sie nicht, dass gültige Indizes von
0
bis sindLength - 1
. Wenn Sie einfach versuchen, ein Element zuzuweisen, erhaltenLength
SieIndexOutOfRangeException
(dieses Verhalten kann Sie verwirren, wenn Sie glauben, dass es mit einer Syntax zunimmt, die derInsert
Methode anderer Sammlungen ähnelt ).Spezielle Arrays mit benutzerdefinierter Untergrenze Das
erste Element in Arrays hat immer den Index 0 . Dies ist nicht immer der Fall, da Sie ein Array mit einer benutzerdefinierten Untergrenze erstellen können:
In diesem Beispiel sind Array-Indizes von 1 bis 4 gültig. Natürlich kann die Obergrenze nicht geändert werden.
Falsche Argumente
Wenn Sie mit nicht validierten Argumenten (von Benutzereingaben oder vom Funktionsbenutzer) auf ein Array zugreifen, wird möglicherweise folgende Fehlermeldung angezeigt:
Unerwartete Ergebnisse
Diese Ausnahme kann auch aus einem anderen Grund ausgelöst werden: Konventionell geben viele Suchfunktionen -1 zurück (nullables wurde mit .NET 2.0 eingeführt und es ist auch eine bekannte Konvention, die seit vielen Jahren verwendet wird), wenn dies nicht der Fall ist. nichts finden. Stellen Sie sich vor, Sie haben eine Reihe von Objekten, die mit einer Zeichenfolge vergleichbar sind. Sie könnten denken, diesen Code zu schreiben:
Dies schlägt fehl, wenn keine Elemente in der
myArray
Suchbedingung erfüllt sind, daArray.IndexOf()
-1 zurückgegeben wird und der Array-Zugriff ausgelöst wird.Das nächste Beispiel ist ein naives Beispiel für die Berechnung des Auftretens eines bestimmten Satzes von Zahlen (Kenntnis der maximalen Anzahl und Rückgabe eines Arrays, bei dem Element bei Index 0 für Nummer 0 steht, Elemente bei Index 1 für Nummer 1 usw.):
Natürlich ist es eine ziemlich schreckliche Implementierung, aber was ich zeigen möchte, ist, dass es bei negativen Zahlen und Zahlen oben fehlschlägt
maximum
.Wie es gilt
List<T>
?Gleiche Fälle wie Array - Bereich gültiger Indizes - 0 (
List
die Indizes beginnen immer mit 0) bislist.Count
- Zugriff auf Elemente außerhalb dieses Bereichs verursachen die Ausnahme.Beachten Sie, dass
List<T>
wirftArgumentOutOfRangeException
für dieselben Fälle gelten, in denen Arrays verwendet werdenIndexOutOfRangeException
.Im Gegensatz zu Arrays wird der
List<T>
Start leer. Der Versuch, auf Elemente der gerade erstellten Liste zuzugreifen, führt zu dieser Ausnahme.Häufig führt das Auffüllen einer Liste mit Indizierung (ähnlich wie
Dictionary<int, T>
) zu einer Ausnahme:IDataReader und Spalten
Stellen Sie sich vor, Sie versuchen, Daten aus einer Datenbank mit diesem Code zu lesen:
GetString()
wird werfen,IndexOutOfRangeException
weil Ihr Datensatz nur zwei Spalten hat, aber Sie versuchen, einen Wert von der dritten zu erhalten (Indizes sind immer auf 0).Bitte beachten Sie, dass dieses Verhalten mit den meisten
IDataReader
Implementierungen geteilt wird (SqlDataReader
,OleDbDataReader
usw.).Sie können dieselbe Ausnahme auch erhalten, wenn Sie die IDataReader-Überladung des Indexeroperators verwenden, der einen Spaltennamen verwendet und einen ungültigen Spaltennamen übergibt.
Angenommen, Sie haben eine Spalte mit dem Namen Column1 abgerufen, versuchen dann aber, den Wert dieses Felds mit abzurufen
Dies liegt daran, dass der Indexeroperator implementiert ist und versucht, den Index eines Colum1 abzurufen dass nicht vorhandenen Felds . Die GetOrdinal-Methode löst diese Ausnahme aus, wenn ihr interner Hilfscode -1 als Index für "Colum1" zurückgibt.
Andere
Es gibt einen anderen (dokumentierten) Fall, in dem diese Ausnahme ausgelöst wird: Wenn der
DataView
Name der Datenspalte an dieDataViewSort
Eigenschaft übergeben wird, ungültig ist.Wie zu vermeiden
Lassen Sie mich in diesem Beispiel der Einfachheit halber annehmen, dass Arrays immer monodimensional und 0-basiert sind. Wenn Sie streng sein wollen (oder Sie entwickeln eine Bibliothek), müssen Sie ersetzen
0
mitGetLowerBound(0)
und.Length
mitGetUpperBound(0)
(natürlich nur, wenn Sie die Parameter des Typs habenSystem.Arra
y, gilt sie nicht fürT[]
). Bitte beachten Sie, dass in diesem Fall die Obergrenze den folgenden Code enthält:Sollte folgendermaßen umgeschrieben werden:
Bitte beachten Sie, dass dies nicht zulässig ist (es wird geworfen
InvalidCastException
). Wenn Ihre ParameterT[]
sicher sind, können Sie daher benutzerdefinierte Arrays mit niedrigeren Grenzen verwenden:Parameter validieren
Wenn der Index von einem Parameter stammt, sollten Sie diese immer validieren (entsprechend werfen
ArgumentException
oderArgumentOutOfRangeException
). Im nächsten Beispiel können falsche Parameter dazu führenIndexOutOfRangeException
, dass Benutzer dieser Funktion dies erwarten, weil sie ein Array übergeben, dies jedoch nicht immer so offensichtlich ist. Ich würde vorschlagen, immer Parameter für öffentliche Funktionen zu validieren:Wenn die Funktion privat ist, können Sie die
if
Logik einfach durch Folgendes ersetzenDebug.Assert()
:Check Object State
Array-Index stammt möglicherweise nicht direkt von einem Parameter. Es kann Teil des Objektzustands sein. Im Allgemeinen ist es immer eine gute Praxis, den Objektstatus zu validieren (für sich und bei Bedarf mit Funktionsparametern). Sie können
Debug.Assert()
eine geeignete Ausnahme verwenden (das Problem genauer beschreiben) oder wie in diesem Beispiel behandeln:Rückgabewerte validieren
In einem der vorherigen Beispiele haben wir den
Array.IndexOf()
Rückgabewert direkt verwendet . Wenn wir wissen, dass es fehlschlagen kann, ist es besser, diesen Fall zu behandeln:So debuggen Sie
Meiner Meinung nach können die meisten Fragen hier auf SO zu diesem Fehler einfach vermieden werden. Die Zeit, die Sie zum Schreiben einer richtigen Frage (mit einem kleinen Arbeitsbeispiel und einer kleinen Erklärung) aufwenden, kann leicht viel mehr sein als die Zeit, die Sie zum Debuggen Ihres Codes benötigen. Lesen Sie zunächst den Blog-Beitrag von Eric Lippert über das Debuggen kleiner Programme . Ich werde seine Worte hier nicht wiederholen, aber es ist absolut ein Muss .
Sie haben Quellcode, Sie haben eine Ausnahmemeldung mit einem Stack-Trace. Gehen Sie dorthin, wählen Sie die richtige Zeilennummer und Sie werden sehen:
Sie haben Ihren Fehler gefunden, überprüfen Sie, wie sich
index
erhöht. Ist es richtig? Überprüfen Sie, wie das Array zugewiesen wird. Stimmt dies mit denindex
Erhöhungen überein? Ist es richtig nach Ihren Vorgaben? Wenn Sie mit Ja antworten all diese Fragen mit beantworten, finden Sie hier auf StackOverflow gute Hilfe. Überprüfen Sie dies jedoch zunächst selbst. Sie sparen Ihre eigene Zeit!Ein guter Ausgangspunkt ist, immer Zusicherungen zu verwenden und Eingaben zu validieren. Möglicherweise möchten Sie sogar Codeverträge verwenden. Wenn etwas schief gelaufen ist und Sie mit einem kurzen Blick auf Ihren Code nicht herausfinden können, was passiert, müssen Sie auf einen alten Freund zurückgreifen: den Debugger . Führen Sie einfach Ihre Anwendung im Debug in Visual Studio (oder Ihrer bevorzugten IDE) aus. Sie sehen genau, welche Zeile diese Ausnahme auslöst, welches Array betroffen ist und welchen Index Sie verwenden möchten. Wirklich, 99% der Fälle lösen Sie es in wenigen Minuten selbst.
Wenn dies in der Produktion passiert, sollten Sie Behauptungen in belasteten Code einfügen. Wahrscheinlich sehen wir in Ihrem Code nicht, was Sie selbst nicht sehen können (aber Sie können immer wetten).
Die VB.NET-Seite der Geschichte
Alles, was wir in der C # -Antwort gesagt haben, gilt für VB.NET mit den offensichtlichen Syntaxunterschieden. Es ist jedoch ein wichtiger Punkt zu beachten, wenn Sie mit VB.NET-Arrays arbeiten.
In VB.NET werden Arrays deklariert, die den maximal gültigen Indexwert für das Array festlegen. Es ist nicht die Anzahl der Elemente, die wir im Array speichern möchten.
Diese Schleife füllt das Array also mit 5 Ganzzahlen, ohne eine IndexOutOfRangeException zu verursachen
Die VB.NET-Regel
Diese Ausnahme bedeutet, dass Sie versuchen, mit einem ungültigen Index indexweise auf ein Sammlungselement zuzugreifen. Ein Index ist ungültig, wenn er niedriger als die Untergrenze der Sammlung oder größer als ist
gleich der Anzahl der darin enthaltenen Elemente.Der maximal zulässige Index, der in der Array-Deklaration definiert istquelle
Einfache Erklärung, was ein Index außerhalb der gebundenen Ausnahme ist:
Denken Sie nur, ein Zug ist da, seine Abteile sind D1, D2, D3. Ein Passagier stieg in den Zug ein und hat das Ticket für D4. Was wird jetzt passieren? Der Passagier möchte ein Abteil betreten, das nicht existiert, so dass offensichtlich ein Problem auftritt.
Gleiches Szenario: Wenn wir versuchen, auf eine Array-Liste usw. zuzugreifen, können wir nur auf die vorhandenen Indizes im Array zugreifen.
array[0]
undarray[1]
sind vorhanden. Wenn wir versuchen, darauf zuzugreifenarray[3]
, ist es tatsächlich nicht vorhanden, sodass ein Index außerhalb der gebundenen Ausnahme entsteht.quelle
Stellen Sie sich vor, wir haben diesen Code geschrieben, um das Problem leicht zu verstehen:
Ergebnis wird sein:
Die Größe des Arrays beträgt 3 (Indizes 0, 1 und 2), aber die for-Schleife wiederholt sich viermal (0, 1, 2 und 3).
Wenn also versucht wird, mit (3) außerhalb der Grenzen zuzugreifen, wird die Ausnahme ausgelöst.
quelle
Neben der sehr langen, vollständig akzeptierten Antwort ist im
IndexOutOfRangeException
Vergleich zu vielen anderen Ausnahmetypen ein wichtiger Punkt zu beachten, und zwar:Oft gibt es einen komplexen Programmstatus, über den an einem bestimmten Punkt im Code möglicherweise nur schwer die Kontrolle zu haben ist, z. B. wenn eine DB-Verbindung ausfällt, sodass Daten für eine Eingabe nicht abgerufen werden können usw. Diese Art von Problem führt häufig zu einer Ausnahme muss auf eine höhere Ebene aufsteigen, weil es an diesem Punkt keine Möglichkeit gibt, damit umzugehen, wo es auftritt.
IndexOutOfRangeException
ist im Allgemeinen insofern anders, als es in den meisten Fällen ziemlich trivial ist, an dem Punkt zu prüfen, an dem die Ausnahme ausgelöst wird. Im Allgemeinen wird diese Art von Ausnahme durch einen Code ausgelöst, der das Problem an der Stelle, an der es auftritt, sehr leicht beheben kann - nur durch Überprüfen der tatsächlichen Länge des Arrays. Sie möchten dies nicht beheben, indem Sie diese Ausnahme höher behandeln, sondern sicherstellen, dass sie nicht in erster Linie ausgelöst wird. Dies ist in den meisten Fällen einfach, indem Sie die Array-Länge überprüfen.Eine andere Möglichkeit, dies auszudrücken, besteht darin, dass andere Ausnahmen aufgrund eines echten Mangels an Kontrolle über die Eingabe oder den Programmstatus auftreten können, ABER
IndexOutOfRangeException
meistens ist es einfach nur ein Pilotfehler (Programmierer).quelle