为啥 List<T> 的“索引超出范围”异常,但数组却没有?

Posted

技术标签:

【中文标题】为啥 List<T> 的“索引超出范围”异常,但数组却没有?【英文标题】:Why "Index was out of range" exception for List<T> but not for arrays?为什么 List<T> 的“索引超出范围”异常,但数组却没有? 【发布时间】:2016-05-05 20:09:31 【问题描述】:

当我使用索引器初始化数组并访问元素时,效果很好:

object[] temp = new object[5];
temp[0] = "bar";

现在我希望 List&lt;T&gt; 也可以使用同样的方法,因为您可以通过将容量传递给构造函数来对其进行初始化:

List<object> temp = new List<object>(5);
temp[0] = "bar";

然而,最后一行会引发以下异常:

索引超出范围。必须是非负数且小于集合的大小

为什么List&lt;T&gt; 类型会发生这种情况,而不是数组?既然数组只是 CLR 集合的低级抽象,那么为什么会出现这个异常呢?


question原创Awais Mahmood。

【问题讨论】:

你可以找到关于这个问题的所有元讨论over here。 @RobertHarvey:谢谢——尽管如此,我还是重新添加了关于原作者的简短评论,因为我不想看起来像一个抄袭者,在不给予信任的情况下复制别人的问题。跨度> 【参考方案1】:

简答:因为 5 做了非常不同的事情。

长答案:

当初始化一个数组时,你设置它的大小,这个大小是固定的。阵列以后不能增长或缩小。因此,

object[] temp = new object[5];

表示您创建一个包含 5 个元素的新数组。因此,您可以在创建数组后立即访问这些元素。

对于列表,大小是可变的。 List&lt;T&gt; class 的实例在内部使用一个数组来存储它们的项目,当您在列表中添加或删除项目时,该数组将被更大或更小的数组替换。在每种情况下,列表中保留的所有项目都会从前一个数组复制到新数组。由于这是一项相当昂贵的操作,内部数组有一些未使用项的开销。只要将项目添加到列表中并且不超过该内部数组的大小,就不需要替换该数组。

您传递给列表构造函数的 5 是该内部数组的初始大小:

List<object> temp = new List<object>(5);

这意味着,您创建的列表有 零个元素(因此例外),但内部数组初始化为 5 的大小,因此您可以添加 5 个元素而不需要内部数组被替换。

【讨论】:

@SririamSakthivel:感谢您的编辑。然而,我真的认为replacedresized 更有意义。答案的重点是数组不会得到resized,但列表中有一个内部数组替换为新的、更大或更小的数组实例。 也许你应该提到要修复他的列表代码,他应该将行从temp[i] = criteria[i + 1].ToString();更改为temp.Add(criteria[i + 1].ToString());

以上是关于为啥 List<T> 的“索引超出范围”异常,但数组却没有?的主要内容,如果未能解决你的问题,请参考以下文章

为啥此代码显示参数索引超出范围异常? [复制]

为啥在遍历列表矩阵时出现列表索引超出范围错误?

为啥索引超出范围的子字符串切片有效?

为啥在使用 readlines() 读取文件时出现列表索引超出范围错误?

表格视图单元格中的 uicollectionview 出现错误:索引超出范围,为啥?

当切片索引超出范围时如何引发 IndexError?