Error System.Collctions MoveNextRare

patrick

Well-known member
Joined
Dec 5, 2021
Messages
305
Programming Experience
1-3
Hello

Please Help me

System.InvalidOperationException Collection was modified; enumeration operation may not execute.
at System.Collctions.Generic.List'1.Enumeraor.MoveNextRare()
at System.Linq.Enumerable.WhereListIterator'1.MoveNext()
at System.Linq.Butter'1.ctor(IEnumerable'1 source)

C#:
        public string GetMList(ref MDataFormat mts, bool setItem = false)
        {
            string ret = null;

            Dictionary<string, string> delList;
            delList = mts.DeleteOverLayer();

            bool isTail = false;
            Dictionary<string, int> addID = AddSetValueIDsAtMTS(ref mts, out isTail);
            if (isTail) return ret;


            DBAttrListDataFormat dbAttrViewList = DBAttrList.Instance(DBName).DBAttrViewList;

            int viewtypeidx = dbAttrViewList.cols.FindIndex(x => x.Equals("type", StringComparison.OrdinalIgnoreCase));

            IEnumerable<string[]> DBAttrListResult;

            Func<string, int> customConvertToInt32 = (s) =>
            {
                int y = 0;
                for (int i = 0; i < s.Length; i++)
                    y = y * 10 + (s[i] - '0');
                return y;
            };


            if (mts.ViewLayer > 0 && viewtypeidx > -1)
                DBAttrListResult = dbAttrViewList.rows.Where(x => customConvertToInt32(x[layeridx]) >= customConvertToInt32(mLayer)).Where(x => x[viewtypeidx] == viewtype.SelValue);
            else
                DBAttrListResult = dbAttrViewList.rows.Where(x => x[layeridx] == mLayer);

            try
            {
                DBAttrListResult = DBAttrListResult.OrderBy(x => customConvertToInt32(x[depthidx]));
            }
            finally
            {
            }

            if (mts.ViewLayer == 1)
                delList.Clear();


            try
            {
                foreach (string[] row in DBAttrListResult)
                {                 
                    IEnumerable<string[]> valdt = GetAttrSetValueList(key, mts);

                    if (delList.ContainsKey(key))   
                    {
                        bool notContains = false;

                        if (delList[key] != null)
                        {
                            string[] delvaluelist = delList[key].Split(',');

                            foreach (string delvalue in delvaluelist)
                            {
                                if (!mts.AttrList[key].ValueList.Contains(delvalue))
                                {
                                    if (!setFirstItem)
                                    {
                                        mts.AttrList[key].ValueList.Add(delvalue);
                                    }
                                    else
                                    {
                                        notContains = true;
                                    }                                       
                                }
                            }
                        }
                    }             
                }
            }
            catch (Exception e)
            {
                return ret;
            }

            return ret;
        }
 
There's way too much code there. Please keep your code to only what is relevant to the issue. If you need to create test code in order to demonstrate the issue without all the noise of irrelevant code, that's what you do.

Regardless, I don't even need to look at the code to know what's happening, based on the error message. You are enumerating a collection, probably using a foreach loop, and you are modifying the collection in that loop. That is not allowed. If you want to modify a collection then you cannot do so while you're enumerating it. If you need to loop over the items in a collection and also modify the collection then you have some options.

Firstly, you could create a new array or collection, probably by calling ToArray or ToList on the existing collection. You then enumerate the second list, which contains the same items as the first, while modifying the first collection, e.g.
C#:
foreach (var item in myCollection.ToArray())
{
    // Modify myCollection here.
}
Just note that ToArray and ToList will both enumerate the original collection, so that means that you're basically looping over the same items twice. No big deal in most cases but it could be a problem for large collections.

Secondly, you could use a for loop instead and loop backwards. By starting at the end, it means that adding or removing any items at the current index or later will not affect any items yet to be processed, so modifying the collection is not an issue, e.g.
C#:
for (var i = myCollection.Count - 1; i <= 0; i--)
{
    var item = myCollection[i];
    
    // Modify myCollection here.
}
 
In the code where the error occurs:
It appears at System.Linq.Enumerable.WhereListIterator'1.MoveNext() point,

Where is this part(at System.Linq.Enumerable.WhereListIterator'1.MoveNext() point) in the code?


Does locking it solve the problem?
lock has the advantage of not requiring major modifications to existing code.
If the problem is solved with lock, which code should lock be added to in the code where the error occurs?
 
If you're talking about using a lock statement, that's about preventing multiple threads accessing the same section of code at the same time. I don't see any indication that that is the issue.
 
If you're talking about using a lock statement, that's about preventing multiple threads accessing the same section of code at the same time. I don't see any indication that that is the issue.

They say they were suspicious of the code you gave and applied it to the code that was causing the problem.

There's way too much code there. Please keep your code to only what is relevant to the issue. If you need to create test code in order to demonstrate the issue without all the noise of irrelevant code, that's what you do.

Regardless, I don't even need to look at the code to know what's happening, based on the error message. You are enumerating a collection, probably using a foreach loop, and you are modifying the collection in that loop. That is not allowed. If you want to modify a collection then you cannot do so while you're enumerating it. If you need to loop over the items in a collection and also modify the collection then you have some options.

Firstly, you could create a new array or collection, probably by calling ToArray or ToList on the existing collection. You then enumerate the second list, which contains the same items as the first, while modifying the first collection, e.g.
C#:
foreach (var item in myCollection.ToArray())
{
    // Modify myCollection here.
}
Just note that ToArray and ToList will both enumerate the original collection, so that means that you're basically looping over the same items twice. No big deal in most cases but it could be a problem for large collections.

Secondly, you could use a for loop instead and loop backwards. By starting at the end, it means that adding or removing any items at the current index or later will not affect any items yet to be processed, so modifying the collection is not an issue, e.g.
C#:
for (var i = myCollection.Count - 1; i <= 0; i--)
{
    var item = myCollection[i];
   
    // Modify myCollection here.
}



They say they were suspicious of the code you gave and applied it to the code that was causing the problem.

Can I fix this point ( foreach (string[] row in DBAttrListResult) and foreach (string delvalue in delvaluelist) ) in the code where the error occurs?

At what point in the code does the error occur?

foreach (var item in myCollection.ToArray())
{
// Modify myCollection here.
}

for (var i = myCollection.Count - 1; i <= 0; i--)
{
var item = myCollection;

// Modify myCollection here.
}
 
In the code where the error occurs:
It appears at System.Linq.Enumerable.WhereListIterator'1.MoveNext() point,

Where is this part(at System.Linq.Enumerable.WhereListIterator'1.MoveNext() point) in the code?

LINQ is based on the IEnumerable<T> interface and extensions methods you can call on it. When you call LINQ methods, they return a (usually custom) IEnumerable<T> that you can then enumerate. You are calling the Where extension method and, when you enumerate the result of that, a WhereListEnumetaror<T> will be created under the hood in order to do so. When you enumerate an IEnumerable<T>, an IEnumerator<T> is created to do the work. A foreach loop is just syntactic sugar over that.
 
I don't understand your last post. Who is "they"? Why are you asking us where the problem occurs? I've provided you with a principle. You need to debug the code, work out which collection is being modified and then apply the principle to it. We can't run your code, because you've just posted a method in isolation, so we can't test it and see what it does. You have the debugger for that.
 
LINQ is based on the IEnumerable<T> interface and extensions methods you can call on it. When you call LINQ methods, they return a (usually custom) IEnumerable<T> that you can then enumerate. You are calling the Where extension method and, when you enumerate the result of that, a WhereListEnumetaror<T> will be created under the hood in order to do so. When you enumerate an IEnumerable<T>, an IEnumerator<T> is created to do the work. A foreach loop is just syntactic sugar over that.


Can I modify this part (
foreach (string[] row in DBAttrListResult)
foreach (string delvalue in delvaluelist))
of the code below like this (
for (var i = myCollection.Count - 1; i <= 0; i--)
{
var item = myCollection;

// Modify myCollection here.
}
)

?


please answer me





How do I modify (
IEnumerable<string[]> DBAttrListResult;
foreach (string[] row in DBAttrListResult)
{
string key = row[1];
string name = row[2];
string hown = row[2];
})
TO
for (var i = myCollection.Count - 1; i <= 0; i--)
{
var item = myCollection;

// Modify myCollection here.
}

?





C#:
 public string GetMList(ref MDataFormat mts, bool setItem = false)
        {
            string ret = null;

            Dictionary<string, string> delList;
            delList = mts.DeleteOverLayer();

            bool isTail = false;
            Dictionary<string, int> addID = AddSetValueIDsAtMTS(ref mts, out isTail);
            if (isTail) return ret;


            DBAttrListDataFormat dbAttrViewList = DBAttrList.Instance(DBName).DBAttrViewList;

            int viewtypeidx = dbAttrViewList.cols.FindIndex(x => x.Equals("type", StringComparison.OrdinalIgnoreCase));

            IEnumerable<string[]> DBAttrListResult;

            Func<string, int> customConvertToInt32 = (s) =>
            {
                int y = 0;
                for (int i = 0; i < s.Length; i++)
                    y = y * 10 + (s[i] - '0');
                return y;
            };


            if (mts.ViewLayer > 0 && viewtypeidx > -1)
                DBAttrListResult = dbAttrViewList.rows.Where(x => customConvertToInt32(x[layeridx]) >= customConvertToInt32(mLayer)).Where(x => x[viewtypeidx] == viewtype.SelValue);
            else
                DBAttrListResult = dbAttrViewList.rows.Where(x => x[layeridx] == mLayer);

            try
            {
                DBAttrListResult = DBAttrListResult.OrderBy(x => customConvertToInt32(x[depthidx]));
            }
            finally
            {
            }

            if (mts.ViewLayer == 1)
                delList.Clear();


            try
            {
                foreach (string[] row in DBAttrListResult)
                {             
                    IEnumerable<string[]> valdt = GetAttrSetValueList(key, mts);

                    if (delList.ContainsKey(key))
                    {
                        bool notContains = false;

                        if (delList[key] != null)
                        {
                            string[] delvaluelist = delList[key].Split(',');

                            foreach (string delvalue in delvaluelist)
                            {
                                if (!mts.AttrList[key].ValueList.Contains(delvalue))
                                {
                                    if (!setFirstItem)
                                    {
                                        mts.AttrList[key].ValueList.Add(delvalue);
                                    }
                                    else
                                    {
                                        notContains = true;
                                    }                                   
                                }
                            }
                        }
                    }         
                }
            }
            catch (Exception e)
            {
                return ret;
            }

            return ret;
        }
 
Last edited:
Take a step back. Have you identified which collection is being modified and where that's happening? If not, use the debugger to do so. If so, provide that information to us.
 
Take a step back. Have you identified which collection is being modified and where that's happening? If not, use the debugger to do so. If so, provide that information to us.

I changed it like this: Can I change it like this?


C#:
   string[] delvaluelist = delList[key].Split(',');



                            [U][B]foreach (string delvalue in delvaluelist)[/B][/U]
                            {
                                if (!mts.AttrList[key].ValueList.Contains(delvalue))
                                {
                                    if (!setFirstItem)
                                    {
                                        mts.AttrList[key].ValueList.Add(delvalue);
                                    }
                                    else
                                    {
                                        notContains = true;
                                    }                              
                               }
                           }

===>

 string[] delvaluelist = delList[key].Split(',');

                            [B][U]for (int i = 0; i < delvaluelist.Length; i++)[/U][/B]
                            {
                                if (!mts.AttrList[key].ValueList.Contains(delvaluelist))
                                {
                                    if (!setFirstItem)
                                    {
                                        mts.AttrList[key].ValueList.Add(delvaluelist);
                                        mts.AttrList[key].ValueListShown.Add(delvaluelist);
                                    }
                                    else notContains = true;
                                }
                            }


Do you have any doubts?

System.InvalidOperationException Collection was modified; enumeration operation may not execute.
at System.Collctions.Generic.List'1.Enumeraor.MoveNextRare()
at System.Linq.Enumerable.WhereListIterator'1.MoveNext()
at System.Linq.Butter'1.ctor(IEnumerable'1 source)
System.Linq.OrderedEnumerable'1.<GetEnumerator>d__1.MoveNext()

at System.Linq.Enumerable.Any[TSource](IEnumerable'1 source)


C#:
public string GetMList(ref MDataFormat mts, bool setItem = false)
        {
            string ret = null;

            Dictionary<string, string> delList;
            delList = mts.DeleteOverLayer();

            bool isTail = false;
            Dictionary<string, int> addID = AddSetValueIDsAtMTS(ref mts, out isTail);
            if (isTail) return ret;


            DBAttrListDataFormat dbAttrViewList = DBAttrList.Instance(DBName).DBAttrViewList;

            int viewtypeidx = dbAttrViewList.cols.FindIndex(x => x.Equals("type", StringComparison.OrdinalIgnoreCase));

            IEnumerable<string[]> DBAttrListResult;

            Func<string, int> customConvertToInt32 = (s) =>
            {
                int y = 0;
                for (int i = 0; i < s.Length; i++)
                    y = y * 10 + (s[i] - '0');
                return y;
            };


            if (mts.ViewLayer > 0 && viewtypeidx > -1)
                DBAttrListResult = dbAttrViewList.rows.Where(x => customConvertToInt32(x[layeridx]) >= customConvertToInt32(mLayer)).Where(x => x[viewtypeidx] == viewtype.SelValue);
            else
                DBAttrListResult = dbAttrViewList.rows.Where(x => x[layeridx] == mLayer);

            try
            {
                DBAttrListResult = DBAttrListResult.OrderBy(x => customConvertToInt32(x[depthidx]));
            }
            finally
            {
            }

            if (mts.ViewLayer == 1)
                delList.Clear();


            try
            {
                foreach (string[] row in DBAttrListResult)
                {            
                    IEnumerable<string[]> valdt = GetAttrSetValueList(key, mts);

                    if (delList.ContainsKey(key))
                    {
                        bool notContains = false;

                        if (delList[key] != null)
                        {
                            string[] delvaluelist = delList[key].Split(',');

                            foreach (string delvalue in delvaluelist)
                            {
                                if (!mts.AttrList[key].ValueList.Contains(delvalue))
                                {
                                    if (!setFirstItem)
                                    {
                                        mts.AttrList[key].ValueList.Add(delvalue);
                                    }
                                    else
                                    {
                                        notContains = true;
                                    }                                  
                                }
                            }
                        }
                    }        
                }
            }
            catch (Exception e)
            {
                return ret;
            }

            return ret;
        }
 
Last edited:
Back
Top Bottom