所以,我已经使用以下代码了一段时间了,直到最近才抛出例外。
// median-of-medians search:
const int MOM_GROUP_SIZE = 5;
List<KeyValuePair<int, float>> mediansList = indexPositionPairs;
while (mediansList.Count > 1) // could be only one because of outer loop, so check before first (inner) iteration!
{
List<KeyValuePair<int, float>> groupMediansList;
int fullGroupListLength = mediansList.Count / MOM_GROUP_SIZE;
int remainderGroupSize = mediansList.Count % MOM_GROUP_SIZE;
if (remainderGroupSize > 0)
{
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength + 1);
// find last group median
int startingIndex = fullGroupListLength * MOM_GROUP_SIZE;
mediansList.Sort(startingIndex, remainderGroupSize, comp);
groupMediansList[fullGroupListLength] = mediansList[startingIndex + remainderGroupSize / 2];
}
else
{
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength);
}
// groups of 5:
for (int i = 0, j = 0; i < fullGroupListLength; ++i, j += MOM_GROUP_SIZE)
{
mediansList.Sort(j, MOM_GROUP_SIZE, comp);
groupMediansList[i] = mediansList[j + MOM_MEDIAN_OFFSET];
}
// repeat on the group medians until only one remains
mediansList = groupMediansList;
}
现在我从以下行获得ArgumentOutOfRangeException
:
groupMediansList[fullGroupListLength] = mediansList[startingIndex + remainderGroupSize / 2];
特别是左侧,我正在尝试在索引上设置值。我会收到异常消息:
"索引超出范围。必须是非负的,并且小于集合的大小。 r n参数名称:索引"
阅读Microsoft的一些在线文档,似乎当index
大于或等于Count
时,确实应该抛出ArgumentOutOfRangeException
。
但是,正如您可以在代码中进一步看到的那样,我使用相同的方法来填充列表,但从未引起异常。我也非常怀疑这个特定的代码块从未被调用过,因为它需要所有数据集此代码以前使用的所有数据集具有5个自然功率。
。这是我在迄今为止使用此代码的最大数据集(1366921个元素!),那么它会产生任何效果吗?(理想情况下它不应该,但您永远不知道...)
目前,我将使用阵列重新编写它,但是我想了解这里发生了什么。我一直认为,如果列表在列表上超出当前大小,则在列表上进行索引会自动扩展,我担心对我较旧的项目的影响。
首先,使用int
参数INTIAL的List<T>
构造函数使用指定的 apcation ,而不是 length 。这意味着结果列表始终将其初始Count
的零。
其次,只有在调用Add
或Insert
(或AddRange
或InsertRange
)访问索引元素时,列表不会神奇地增长。即使它们确实成长,您仍然不允许您访问Count
和Capacity
之间的任何索引。
我怀疑第二种方法"从不引起异常",因为这是同一问题:您正在创建具有特定容量的空列表,然后立即尝试访问索引超出其数量。C#不像C ,在这里可以将其粉刷为未定义的行为:这里,每次都会抛出。。
由于您的算法似乎是"创建预定长度的列表,然后替换单个元素",因此数组可能更拟合。
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength + 1);
看来,您正在假设将列表的容量设置为fullGroupListLength + 1
的假设使您可以访问指数0到fullGroupListLength
。但是,容量和计数是两种不同的东西。您无法访问大于或等于groupMediansList.Count
的索引。解决方案是将所需数量的值添加到列表中或使用其他集合,例如数组。