defoh 1 / 1 / 0 Регистрация: 31.03.2022 Сообщений: 28 |
||||
1 |
||||
01.04.2022, 13:14. Показов 1400. Ответов 2 Метки unity, unity 3d (Все метки)
Возникает такая ошибка IndexOutOfRangeException: Index was outside the bounds of the array.
__________________
0 |
Алексанierecumi 93 / 59 / 35 Регистрация: 07.08.2013 Сообщений: 241 |
||||
01.04.2022, 13:47 |
2 |
|||
у вас [i] не ограничено длинной массива
0 |
BattleCrow 529 / 341 / 196 Регистрация: 18.10.2019 Сообщений: 1,152 |
||||
01.04.2022, 20:09 |
3 |
|||
defoh, судя по всему возникает ситуация, когда в массиве нет объекта, который бы противоречил этому условию:
while (AllCharacters[i].name != data.currentCharacter) Чтобы избежать ошибки, можно написать так:
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
01.04.2022, 20:09 |
Помогаю со студенческими работами здесь IndexOutOfRangeException: Index was outside the bounds of the array. (ошибка в коде) Ошибка — Runtime exception: System.IndexOutOfRangeException: Index out of the bounds of the array Выдает такую ошибку IndexOutOfRangeException: Index was outside the bounds of the array. Бьюсь уже 3 час над решением Ошибка Index was outside the bounds of the array. Как исправить? Ошибка System.IndexOutOfRangeException: «Index was outside the bounds of the array» Ошибка System.IndexOutOfRangeException: «Index was outside the bounds of the array» Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 3 |
idk what I need to do to be inside the bounds of my array. i think my array is stuck not counting at all or counting to much between my 2 interfaces but idk if thats even the problem with it i just know its an array problem in my CreateSlots
don’t know if this helps but I’m following a unity tutorial called Unity3D equipping items scriptable object inventory system
‘the code’:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class StaticInterface : UserInterface
{
public GameObject[] Slots;
public override void CreateSlots()
{
itemsDisplayed = new Dictionary<GameObject, InventorySlot>();
for (int i = 0; i < inventory.Container.Items.Length; i++)
{
var obj = Slots[i]; //this line is the one unity pointed out
AddEvent(obj, EventTriggerType.PointerEnter, delegate { OnEnter(obj); });
AddEvent(obj, EventTriggerType.PointerExit, delegate { OnExit(obj); });
AddEvent(obj, EventTriggerType.BeginDrag, delegate { OnDragStart(obj); });
AddEvent(obj, EventTriggerType.EndDrag, delegate { OnDragEnd(obj); });
AddEvent(obj, EventTriggerType.Drag, delegate { OnDrag(obj); });
itemsDisplayed.Add(obj, inventory.Container.Items[i]);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
public abstract class UserInterface : MonoBehaviour
{
public Player player;
public InventoryObject inventory;
public Dictionary<GameObject, InventorySlot> itemsDisplayed = new Dictionary<GameObject, InventorySlot>();
void Start()
{
CreateSlots();
}
// Update is called once per frame
void Update()
{
UpdateSlots();
}
public abstract void CreateSlots();//this line is the one unity pointed out
IndexOutOfRangeException: Index was outside the bounds of the array.
at UnityEngine.Experimental.Input.InputActionMapState.ChangePhaseOfAction (UnityEngine.Experimental.Input.InputActionPhase newPhase, UnityEngine.Experimental.Input.InputActionMapState+TriggerState& trigger, UnityEngine.Experimental.Input.InputActionPhase phaseAfterPerformedOrCancelled) [0x000d6] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:845
at UnityEngine.Experimental.Input.InputActionMapState.ProcessControlStateChange (System.Int32 mapIndex, System.Int32 controlIndex, System.Int32 bindingIndex, System.Double time, UnityEngine.Experimental.Input.LowLevel.InputEventPtr eventPtr) [0x00152] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:569
at UnityEngine.Experimental.Input.InputActionMapState.UnityEngine.Experimental.Input.LowLevel.IInputStateChangeMonitor.NotifyControlStateChanged (UnityEngine.Experimental.Input.InputControl control, System.Double time, UnityEngine.Experimental.Input.LowLevel.InputEventPtr eventPtr, System.Int64 mapControlAndBindingIndex) [0x0000f] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:455
at UnityEngine.Experimental.Input.InputManager.FireStateChangeNotifications (System.Int32 deviceIndex, System.Double internalTime, UnityEngine.Experimental.Input.LowLevel.InputEvent* eventPtr) [0x00078] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemInputManager.cs:2963
at UnityEngine.Experimental.Input.InputManager.OnUpdate (UnityEngine.Experimental.Input.InputUpdateType updateType, UnityEngine.Experimental.Input.LowLevel.InputEventBuffer& eventBuffer) [0x00936] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemInputManager.cs:2693
at UnityEngine.Experimental.Input.LowLevel.NativeInputRuntime+<>c__DisplayClass6_0.<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType updateType, System.Int32 eventCount, System.IntPtr eventPtr) [0x00011] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemNativeInputRuntime.cs:110
at UnityEngineInternal.Input.NativeInputSystem.NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType updateType, System.Int32 eventCount, System.IntPtr eventData) [0x00011] in C:buildslaveunitybuildModulesInputPrivateInput.cs:91
(Filename: Library/PackageCache/com.unity.inputsystem@0.1.2-preview/InputSystem/Actions/InputActionMapState.cs Line: 845)
IndexOutOfRangeException: Index was outside the bounds of the array.
at UnityEngine.Experimental.Input.InputActionMapState.GetActionOrNull (UnityEngine.Experimental.Input.InputActionMapState+TriggerState& trigger) [0x00091] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:985
at UnityEngine.Experimental.Input.InputActionMapState.GetActionOrNoneString (UnityEngine.Experimental.Input.InputActionMapState+TriggerState& trigger) [0x00001] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:954
at UnityEngine.Experimental.Input.InputActionMapState.ThrowIfPhaseTransitionIsInvalid (UnityEngine.Experimental.Input.InputActionPhase currentPhase, UnityEngine.Experimental.Input.InputActionPhase newPhase, UnityEngine.Experimental.Input.InputActionMapState+TriggerState& trigger) [0x0006e] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:938
at UnityEngine.Experimental.Input.InputActionMapState.ChangePhaseOfAction (UnityEngine.Experimental.Input.InputActionPhase newPhase, UnityEngine.Experimental.Input.InputActionMapState+TriggerState& trigger, UnityEngine.Experimental.Input.InputActionPhase phaseAfterPerformedOrCancelled) [0x00099] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:837
at UnityEngine.Experimental.Input.InputActionMapState.ProcessControlStateChange (System.Int32 mapIndex, System.Int32 controlIndex, System.Int32 bindingIndex, System.Double time, UnityEngine.Experimental.Input.LowLevel.InputEventPtr eventPtr) [0x00152] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:569
at UnityEngine.Experimental.Input.InputActionMapState.UnityEngine.Experimental.Input.LowLevel.IInputStateChangeMonitor.NotifyControlStateChanged (UnityEngine.Experimental.Input.InputControl control, System.Double time, UnityEngine.Experimental.Input.LowLevel.InputEventPtr eventPtr, System.Int64 mapControlAndBindingIndex) [0x0000f] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemActionsInputActionMapState.cs:455
at UnityEngine.Experimental.Input.InputManager.FireStateChangeNotifications (System.Int32 deviceIndex, System.Double internalTime, UnityEngine.Experimental.Input.LowLevel.InputEvent* eventPtr) [0x00078] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemInputManager.cs:2963
at UnityEngine.Experimental.Input.InputManager.OnUpdate (UnityEngine.Experimental.Input.InputUpdateType updateType, UnityEngine.Experimental.Input.LowLevel.InputEventBuffer& eventBuffer) [0x00936] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemInputManager.cs:2693
at UnityEngine.Experimental.Input.LowLevel.NativeInputRuntime+<>c__DisplayClass6_0.<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType updateType, System.Int32 eventCount, System.IntPtr eventPtr) [0x00011] in J:MazeLibraryPackageCachecom.unity.inputsystem@0.1.2-previewInputSystemNativeInputRuntime.cs:110
at UnityEngineInternal.Input.NativeInputSystem.NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType updateType, System.Int32 eventCount, System.IntPtr eventData) [0x00011] in C:buildslaveunitybuildModulesInputPrivateInput.cs:91
(Filename: Library/PackageCache/com.unity.inputsystem@0.1.2-preview/InputSystem/Actions/InputActionMapState.cs Line: 985)
Что это такое?
Это исключение означает, что вы пытаетесь получить доступ к элементу коллекции по индексу, используя недопустимый индекс. Индекс недействителен, если он ниже нижней границы коллекции или больше или равен количеству элементов, которые он содержит.
Когда оно выдается
Учитывая массив, объявленный как:
byte[] array = new byte[4];
Вы можете получить доступ к этому массиву от 0 до 3, значения за пределами этого диапазона приведут IndexOutOfRangeException
к выбросу. Помните об этом при создании массива и доступе к нему.
Длина массива
В C # обычно массивы основаны на 0. Это означает, что первый элемент имеет индекс 0, а последний элемент имеет индекс Length - 1
(где Length
общее количество элементов в массиве), поэтому этот код не работает:
array[array.Length] = 0;
Кроме того, обратите внимание, что если у вас многомерный массив, то вы не можете использовать Array.Length
для обоих измерений, вы должны использовать 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;
}
}
Верхняя граница не включена
В следующем примере мы создаем необработанный двумерный массив Color
. Каждый элемент представляет пиксель, индексы от (0, 0)
до (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;
}
}
Затем этот код завершится ошибкой, потому что массив основан на 0, а последний (нижний правый) пиксель на изображении равен pixels[imageWidth - 1, imageHeight - 1]
:
pixels[imageWidth, imageHeight] = Color.Black;
В другом сценарии вы можете получить ArgumentOutOfRangeException
для этого кода (например, если вы используете GetPixel
метод в Bitmap
классе).
Arrays Do Not Grow
An array is fast. Very fast in linear search compared to every other collection. It is because items are contiguous in memory so memory address can be calculated (and increment is just an addition). No need to follow a node list, simple math! You pay this with a limitation: they can’t grow, if you need more elements you need to reallocate that array (this may take a relatively long time if old items must be copied to a new block). You resize them with Array.Resize<T>()
, this example adds a new entry to an existing array:
Array.Resize(ref array, array.Length 1);
Don’t forget that valid indices are from 0
to Length - 1
. If you simply try to assign an item at Length
you’ll get IndexOutOfRangeException
(this behavior may confuse you if you think they may increase with a syntax similar to Insert
method of other collections).
Special Arrays With Custom Lower Bound
First item in arrays has always index 0. This is not always true because you can create an array with a custom lower bound:
var array = Array.CreateInstance(typeof(byte), new int[] { 4 }, new int[] { 1 });
In that example, array indices are valid from 1 to 4. Of course, upper bound cannot be changed.
Wrong Arguments
If you access an array using unvalidated arguments (from user input or from function user) you may get this error:
private static string[] RomanNumbers =
new string[] { "I", "II", "III", "IV", "V" };
public static string Romanize(int number)
{
return RomanNumbers[number];
}
Unexpected Results
This exception may be thrown for another reason too: by convention, many search functions will return -1 (nullables has been introduced with .NET 2.0 and anyway it’s also a well-known convention in use from many years) if they didn’t find anything. Let’s imagine you have an array of objects comparable with a string. You may think to write this code:
// 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")]);
Это завершится неудачей, если никакие элементы в myArray
не будут удовлетворять условию поиска, потому Array.IndexOf()
что вернет -1, а затем будет выдан доступ к массиву.
Следующий пример — наивный пример для вычисления вхождений заданного набора чисел (зная максимальное число и возвращая массив, где элемент с индексом 0 представляет число 0, элементы с индексом 1 представляют число 1 и так далее):
static int[] CountOccurences(int maximum, IEnumerable<int> numbers) {
int[] result = new int[maximum 1]; // Includes 0
foreach (int number in numbers)
result[number];
return resu<
}
Конечно, это довольно ужасная реализация, но я хочу показать, что она не будет работать для отрицательных чисел и чисел выше maximum
.
К чему это относится List<T>
?
Те же случаи, что и в массиве — диапазон допустимых индексов — 0 ( List
индексы всегда начинаются с 0) list.Count
— доступ к элементам за пределами этого диапазона вызовет исключение.
Обратите внимание , что List<T>
выдает ArgumentOutOfRangeException
для тех же случаев , когда используются массивы IndexOutOfRangeException
.
В отличие от массивов, List<T>
начинается пустым — поэтому попытка получить доступ к элементам только что созданного списка приводит к этому исключению.
var list = new List<int>();
Обычным случаем является заполнение списка индексацией (аналогично Dictionary<int, T>
), что приведет к исключению:
list[0] = 42; // exception
list.Add(42); // correct
IDataReader и столбцы
Представьте, что вы пытаетесь прочитать данные из базы данных с помощью этого кода:
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()
выдаст IndexOutOfRangeException
, потому что в вашем наборе данных всего два столбца, но вы пытаетесь получить значение из 3-го (индексы всегда основаны на 0).
Пожалуйста, обратите внимание, что это поведение является общим для большинства IDataReader
реализаций ( SqlDataReader
, OleDbDataReader
и так далее).
Вы также можете получить такое же исключение, если используете перегрузку IDataReader оператора индексатора, который принимает имя столбца и передает недопустимое имя столбца.
Предположим, например, что вы извлекли столбец с именем Column1, но затем вы пытаетесь получить значение этого поля с помощью
var data = dr["Colum1"]; // Missing the n in Column1.
Это происходит потому, что реализован оператор индексатора, пытающийся получить индекс поля Colum1, которого не существует. Метод GetOrdinal выдаст это исключение, когда его внутренний вспомогательный код вернет значение -1 в качестве индекса «Colum1».
Прочее
Существует еще один (документированный) случай, когда возникает это исключение: если в DataView
, имя столбца данных, предоставляемое DataViewSort
свойству, недопустимо.
Как избежать
В этом примере позвольте мне для простоты предположить, что массивы всегда одномерны и основаны на 0. Если вы хотите быть строгим (или вы разрабатываете библиотеку), вам может потребоваться заменить 0
на GetLowerBound(0)
и .Length
на GetUpperBound(0)
(конечно, если у вас есть параметры типа System.Arra
y, это не применимо T[]
). Пожалуйста, обратите внимание, что в этом случае верхняя граница включает в себя этот код:
for (int i=0; i < array.Length; i) { }
Должно быть переписано следующим образом:
for (int i=array.GetLowerBound(0); i <= array.GetUpperBound(0); i) { }
Пожалуйста, обратите внимание, что это недопустимо (это приведет InvalidCastException
к выбросу), поэтому, если ваши параметры T[]
заданы, вы можете быть спокойны за пользовательские нижние граничные массивы:
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 }));
}
Проверка параметров
Если индекс исходит из параметра, вы всегда должны проверять их (используя соответствующее ArgumentException
или ArgumentOutOfRangeException
). В следующем примере неправильные параметры могут привести IndexOutOfRangeException
к тому, что пользователи этой функции могут ожидать этого, потому что они передают массив, но это не всегда так очевидно. Я бы посоветовал всегда проверять параметры для общедоступных функций:
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);
}
If function is private you may simply replace if
logic with Debug.Assert()
:
Debug.Assert(from >= 0 amp;amp; from < array.Length);
Check Object State
Array index may not come directly from a parameter. It may be part of object state. In general is always a good practice to validate object state (by itself and with function parameters, if needed). You can use Debug.Assert()
, throw a proper exception (more descriptive about the problem) or handle that like in this example:
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];
}
}
Validate Return Values
In one of previous examples we directly used Array.IndexOf()
return value. If we know it may fail then it’s better to handle that case:
int index = myArray[Array.IndexOf(myArray, "Debug");
if (index != -1) { } else { }
How to Debug
In my opinion, most of the questions, here on SO, about this error can be simply avoided. The time you spend to write a proper question (with a small working example and a small explanation) could easily much more than the time you’ll need to debug your code. First of all, read this Eric Lippert’s blog post about debugging of small programs, I won’t repeat his words here but it’s absolutely a must read.
You have source code, you have exception message with a stack trace. Go there, pick right line number and you’ll see:
array[index] = newValue;
Вы нашли свою ошибку, проверьте, как index
увеличивается. Правильно ли это? Проверьте, как распределяется массив, согласуется с тем, как index
увеличивается? Правильно ли это в соответствии с вашими спецификациями? Если вы ответите «да» на все эти вопросы, то вы найдете хорошую помощь здесь, в StackOverflow, но, пожалуйста, сначала проверьте это самостоятельно. Вы сэкономите свое время!
Хорошей отправной точкой является всегда использовать утверждения и проверять входные данные. Возможно, вы даже захотите использовать контракты кода. Когда что-то пошло не так, и вы не можете понять, что происходит, быстро взглянув на свой код, тогда вам придется прибегнуть к старому другу: debugger. Просто запустите свое приложение в режиме отладки внутри Visual Studio (или вашей любимой IDE), вы точно увидите, какая строка выдает это исключение, какой массив задействован и какой индекс вы пытаетесь использовать. Действительно, в 99% случаев вы решите это самостоятельно за несколько минут.
Если это происходит в процессе производства, то вам лучше добавить утверждения в инкриминируемый код, вероятно, мы не увидим в вашем коде то, чего вы не видите сами (но вы всегда можете поспорить).
VB.NET сторона истории
Все, что мы сказали в ответе C #, действительно для VB.NET с очевидными синтаксическими различиями, но есть важный момент, который следует учитывать, когда вы имеете дело с VB.NET массивы.
В VB.NET , массивы объявляются с указанием максимально допустимого значения индекса для массива. Это не количество элементов, которые мы хотим сохранить в массиве.
' declares an array with space for 5 integer
' 4 is the maximum valid index starting from 0 to 4
Dim myArray(4) as Integer
Таким образом, этот цикл заполнит массив 5 целыми числами, не вызывая никакого исключения IndexOutOfRangeException
For i As Integer = 0 To 4
myArray(i) = i
Next
В VB.NET правило
Это исключение означает, что вы пытаетесь получить доступ к элементу коллекции по индексу, используя недопустимый индекс. Индекс является недопустимым, если он меньше нижней границы коллекции или больше, чем равно количеству элементов, которые он содержит. максимально допустимый индекс, определенный в объявлении массива