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.