C# 什么是IndexOutOfRangeException/ArgumentOutOfRangeException,如何修复它?
我有一些代码,当它执行时,它抛出一个C# 什么是IndexOutOfRangeException/ArgumentOutOfRangeException,如何修复它?,c#,.net,indexoutofrangeexception,C#,.net,Indexoutofrangeexception,我有一些代码,当它执行时,它抛出一个索引autofrangeexception,说 索引超出了数组的边界 这意味着什么,我能做些什么 根据所使用的类,它也可以是ArgumentOutOfRangeException mscorlib.dll中发生“System.ArgumentOutOfRangeException”类型的异常,但未在用户代码中处理其他信息:索引超出范围。必须为非负数且小于集合的大小 它是什么? 此异常表示您试图使用无效索引按索引访问集合项。如果索引低于集合的下限或大于或等于其包
索引autofrangeexception
,说
索引超出了数组的边界
这意味着什么,我能做些什么
根据所使用的类,它也可以是ArgumentOutOfRangeException
mscorlib.dll中发生“System.ArgumentOutOfRangeException”类型的异常,但未在用户代码中处理其他信息:索引超出范围。必须为非负数且小于集合的大小
它是什么?
此异常表示您试图使用无效索引按索引访问集合项。如果索引低于集合的下限或大于或等于其包含的元素数,则该索引无效
当它被抛出时
给定声明为的数组:
byte[] array = new byte[4];
您可以从0到3访问此数组,超出此范围的值将导致引发indexootfrangeexception
。创建和访问阵列时请记住这一点
数组长度在C#中,数组通常是基于0的。这意味着第一个元素的索引为0,最后一个元素的索引为
Length-1
(其中Length
是数组中的项目总数),因此此代码不起作用:
array[array.Length] = 0;
此外,请注意,如果您有一个多维数组,则不能对这两个维度都使用array.Length
,必须使用array.GetLength()
:
该代码将失败,因为数组是基于0的,并且图像中的最后一个(右下)像素是像素[imageWidth-1,imageHeight-1]
:
pixels[imageWidth, imageHeight] = Color.Black;
在另一种情况下,您可能会为此代码获取ArgumentOutOfRangeException
(例如,如果您在位图
类上使用GetPixel
方法)
阵列不会增长阵列速度很快。与其他收藏相比,线性搜索速度非常快。这是因为项在内存中是连续的,所以可以计算内存地址(增量只是一个加法)。不需要遵循节点列表,简单的数学!您为此付出的代价有一个限制:如果您需要更多的元素来重新分配该数组,则它们无法增长(如果必须将旧项复制到新块中,这可能需要相对较长的时间)。使用
Array.resize()
Array.Resize(ref array, array.Length + 1);
不要忘记有效的索引是从0
到Length-1
。如果您只是尝试在长度
处分配一个项目,您将得到IndexOutOfRangeException
(如果您认为它们可能会随着语法类似于其他集合的插入
方法而增加,则此行为可能会让您感到困惑)
具有自定义下限的特殊数组
数组中的第一项始终具有索引0。这并不总是正确的,因为您可以创建具有自定义下限的数组:
var array = Array.CreateInstance(typeof(byte), new int[] { 4 }, new int[] { 1 });
在该示例中,数组索引的有效范围为1到4。当然,上限不能改变
错误的参数
如果使用未验证的参数(从用户输入或从函数用户)访问数组,可能会出现以下错误:
private static string[] RomanNumbers =
new string[] { "I", "II", "III", "IV", "V" };
public static string Romanize(int number)
{
return RomanNumbers[number];
}
意外结果
引发此异常可能还有另一个原因:按照惯例,许多搜索函数如果没有找到任何内容,将返回-1(nullables已在.NET2.0中引入,无论如何,这也是多年来使用的一个众所周知的约定)。让我们假设您有一个与字符串相当的对象数组。您可以考虑编写以下代码:
// 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")]);
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!
}
}
}
}
for (int i=0; i < array.Length; ++i) { }
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());
}
}
如果myArray
中没有任何项满足搜索条件,则此操作将失败,因为Array.IndexOf()
将返回-1,然后数组访问将抛出
下一个示例是计算给定数字集出现次数的简单示例(知道最大数字并返回一个数组,其中索引0处的项表示数字0,索引1处的项表示数字1,依此类推):
通常情况下,使用索引填充列表(类似于字典
)会导致异常:
list[0] = 42; // exception
list.Add(42); // correct
IDataReader和列
假设您正试图使用以下代码从数据库读取数据:
// 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")]);
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!
}
}
}
}
for (int i=0; i < array.Length; ++i) { }
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());
}
}
GetString()
将抛出indexootfrangeexception
,因为数据集只有两列,但您试图从第三列获取值(索引总是基于0)
请注意,大多数IDataReader
实现(SqlDataReader
,OleDbDataReader
等等)都有这种行为
如果使用indexer运算符的IDataReader重载获取列名并传递无效列名,也会出现相同的异常。
例如,假设您检索了一个名为Column1的列,但随后尝试使用
var data = dr["Colum1"]; // Missing the n in Column1.
之所以会发生这种情况,是因为indexer运算符是在尝试检索不存在的Colum1字段的索引时实现的。当内部帮助程序代码返回-1作为“Colum1”的索引时,GetOrdinal方法将引发此异常
其他人
引发此异常时还有另一种(记录在案的)情况:如果在DataView
中,提供给DataViewSort
属性的数据列名无效
如何避免
在这个例子中,为了简单起见,让我假设数组总是一维的,并且是基于0的。如果你想严格(或者你正在开发一个库),你可能需要用GetLowerBound(0)
替换0
,用GetUpperBound(0)
替换Length
(当然,如果你有System.Arra
y类型的参数,它不适用于t[]
)。请注意,在这种情况下,上界包含在内,然后此代码:
// 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")]);
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!
}
}
}
}
for (int i=0; i < array.Length; ++i) { }
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());
}
}
验证参数
如果索引
int index = myArray[Array.IndexOf(myArray, "Debug");
if (index != -1) { } else { }
array[index] = newValue;
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());
}
}
hello1
hello2
hello3
Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.