为什么调用我的列表<点>.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# 的问题,由于我对这门语言非常陌生,我想知道我是否不理解某些东西。

为什么调用我的列表<点>.Clear() 抛出一个 ArgumentOutOfRangeException

我认为

您的例外是当您尝试访问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

因此,在类似情况下,集合很可能绑定到内部使用某些异步调用的内容。无论您是否有权访问它。

相关文章:
  • 没有找到相关文章