为什么调用我的列表<点>.Clear() 抛出一个 ArgumentOutOfRangeException
本文关键字:ArgumentOutOfRangeException 一个 Clear 我的 调用 列表 为什么 | 更新日期: 2023-09-27 18:26:26
我有一个应该经常清除的List<Point>
,因为这些值每次迭代使用一次,并且在调用 Clear()
方法时得到ArgumentOutOfRangeException
。
读过一个关于多线程的解释,但据我所知,我没有创建任何线程(除非 c# 以某种方式自动执行 for 或 while 循环到线程中,但我对此表示怀疑(。
这是我的代码:
List<Point> temp = new List<Point>();
List<Point> visited = new List<Point>();
// other initializations
for(int i = 0; i < points.Count;i++){
if(temp.Count != 0)
temp.Clear(); // Problem occurs here
temp.Add(A);
temp.Add(B);
temp.Add(C);
temp.Add(D);
while(!(visited.Contains(temp[0]) && visited.Contains(temp[1])...){
// calculate some stuff
for(int j = 0; j <4;j++)
visited.Add(temp[j]);
// use point of interests
temp.Clear(); // no issue on this clear
temp.Add(newA);
temp.Add(newB);
temp.Add(newC);
temp.Add(newD);
}
// display results
}
它从第一个temp.Clear()
调用中抛出 ArgumentOutOfRangeException。
我还注意到,如果我清除与问题temp.Clear()
相同位置的访问列表,则会出现相同的错误。
对我来说,这似乎是一个特定于 c# 的问题,由于我对这门语言非常陌生,我想知道我是否不理解某些东西。
您的例外是当您尝试访问temp
项时,List.Clear(( 不会抛出ArgumentOutOfRangeException
,因为首先实现 IList.Clear((,最后实现 ICollection.Clear((,他们只是从 .net2 抛出NotSupportedException
到现在而不是ArgumentOutOfRangeException
,如果您在不同的线程中调用您的方法,我想您的问题就在以下行中:
while(!(visited.Contains(temp[0]) && visted.Contains(temp[1])...){
//calculate some stuff
for(int j = 0; j <4;j++)
visited.Add(temp[j]);
你可以通过把这部分包围在lock
块中来解决它。
此外,最好使用visited.Intersect(temp).Count ==0
而不是长期if
状态。
编辑:通过您更新的问题,问题很清楚:
而(...(当前 != 点 [i + 1]((哎呀
当 i = n - 1 时,points[i + 1]
超出范围。
,我不在VS面前,而不是:
temp.Clear();
你能试试吗:
temp = new List<Point>();
这是我拼凑的一些示例代码,它对我来说运行良好:
public void TestPoints()
{
List<Point> temp = new List<Point>();
List<Point> visited = new List<Point>();
List<Point> points = new List<Point>();
points.Add(new Point(100, 100));
points.Add(GeneratePoint());
points.Add(GeneratePoint());
points.Add(GeneratePoint());
points.Add(GeneratePoint());
//other initialization
for (int i = 0; i < points.Count; i++)
{
if (temp.Count != 0)
temp.Clear(); //Problem occurs here
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
while (!(visited.Contains(temp[0]) && visited.Contains(temp[1])))
{
//calculate some stuff
for (int j = 0; j < 4; j++)
visited.Add(temp[j]);
//use point of interests
temp.Clear(); //no issue on this clear
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
temp.Add(GeneratePoint());
}
//display results
}
}
public Point GeneratePoint()
{
return new Point((new Random()).Next(1, 100), (new Random()).Next(1, 100));
}
正如其他人所建议的那样,您是否尝试过"清理"和"重建"您的解决方案。
什么版本的 .NET?它绝不是单声道,是吗?
我倾向于相信你的调试器可能与其他帖子提到的不同步
如果是这种情况,我倾向于认为错误在您没有完整提供给我们的唯一一行上:
while(!(visited.Contains(temp[0]) && visited.Contains(temp[1])...){
它是否访问temp[0] ... temp[3]
或temp[0] ... temp[4]
points[i+1]
在那个while
循环中看起来是错误的(在if()
中(。您的循环转到比最大索引大 1 的 points.Count
。击中那将是一个ArgumentOutOfRangeException
.(除非我忽略了什么。
注意:作为答案而不是评论只是因为这很冗长 - 这不包含问题的解决方案
好的,反编译了通用列表清除方法,它看起来像这样:
public void Clear()
{
if (this._size > 0)
{
Array.Clear(this._items, 0, this._size);
this._size = 0;
}
List`1 list`1s = this;
list`1s._version = list`1s._version + 1;
}
这可能不是线程安全的(如果this._size从"if"条件更改为Array.Clear
行,则可能会出现问题(。 如果提供无效参数,Array.Clear
将引发ArgumentOutOfRange
异常。 见 http://msdn.microsoft.com/en-us/library/system.array.clear.aspx
但是,List<T>.Clear
不可能那么脆弱 - 因此合理的答案包括:代码中的某些内容要么在玩线程,要么不是那一行
因此,作为一种前进的方式,您可以单步执行代码并确认引发错误的Clear()
调用 - 即显示堆栈跟踪
我今天在单击按钮时同步清除 ObservableCollection 时遇到了同样的问题。这是我的解决方法,但如果有人分享有关此的更多信息,我将不胜感激。
public static void RemoveAll<T>(this IList<T> collection)
{
while (collection.Count > 0)
{
if (collection.Count == 1)
{
try
{
collection.RemoveAt(collection.Count - 1);
}
catch (ArgumentOutOfRangeException)
{
if (collection.Count > 0)
throw;
}
}
else
collection.RemoveAt(collection.Count - 1);
}
}
//编辑
好的,现在 Count 抛出了相同的异常,所以我决定更深入地挖掘并发现:
w System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
w Infragistics.FastItemDateTimeColumn.get_Item(Int32 index)
w Infragistics.Controls.Charts.OrdinalTimeXAxis.UpdateActualRange()
w Infragistics.Controls.Charts.OrdinalTimeXAxis.UpdateRangeOverride()
w Infragistics.Controls.Charts.Axis.UpdateRange(Boolean immediate)
w Infragistics.Controls.Charts.OrdinalTimeXAxis.OnFastItemsSourceEvent(FastItemsSourceEventArgs e)
w Infragistics.Controls.Charts.CategoryAxisBase.HandleFastItemsSourceEvent(Object sender, FastItemsSourceEventArgs e)
w System.EventHandler`1.Invoke(Object sender, TEventArgs e)
w Infragistics.FastItemsSource.RaiseDataSourceEvent(FastItemsSourceEventAction action, Int32 position, Int32 count)
w Infragistics.FastItemsSource.dataSourceRemove(Int32 position, IList oldItems)
w Infragistics.FastItemsSource.OnItemsSourceEventProxyWeakCollectionChanged(IFastItemsSource fastItemsSource, Object sender, NotifyCollectionChangedEventArgs e)
w Infragistics.FastItemsSource.<Attach>b__16_0(IFastItemsSource fastItemsSource, Object sender, NotifyCollectionChangedEventArgs e)
w Infragistics.ItemSourceEventProxy.collectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
w System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
w System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
w System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32 index)
w System.Collections.ObjectModel.Collection`1.RemoveAt(Int32 index)
w CryptoBot.Source.Common.Extensions.Extensions.RemoveAll[T](IList`1 collection) w G:'Moje Pliki'Programowanie'CSharp'Projects'CryptoBot'Cryptobot'CryptoBot'Source'Common'Extensions'Extensions.cs:wiersz 1035
因此,在类似情况下,集合很可能绑定到内部使用某些异步调用的内容。无论您是否有权访问它。