c# modifying structs in a List<T>

arrays, c#, foreach

Solution

Looking at the for-loop approach, the reason (and solution) for this is given in the documentation for the compilation error:

An attempt was made to modify a value type that is produced as the result of an intermediate expression but is not stored in a variable. This error can occur when you attempt to directly modify a struct in a generic collection.

To modify the struct, first assign it to a local variable, modify the variable, then assign the variable back to the item in the collection.

So, in your for-loop, change the following lines:

catSlots[s].subItems.Clear();
catSlots[s].subItems = sortedSubTemp;   // ERROR: see below

...into:

slotInfo tempSlot = gAllCats[0].items[s];
tempSlot.subItems  = sortedSubTemp;
gAllCats[0].items[s] = tempSlot;

I removed the call to the `Clear` method, since I don't think it adds anything.

Problem

Short question: How can I modify individual items in a `List`? (or more precisely, members of a `struct` stored in a `List`?) Full explanation: First, the `struct` definitions used below: ``` public struct itemInfo { ...(Strings, Chars, boring)... public String nameStr; ...(you get the idea, nothing fancy)... public String subNum; //BTW this is the element I'm trying to sort on } public struct slotInfo { public Char catID; public String sortName; public Bitmap mainIcon; public IList<itemInfo> subItems; } public struct catInfo { public Char catID; public String catDesc; public IList<slotInfo> items; public int numItems; } catInfo[] gAllCats = new catInfo[31]; ``` `gAllCats` is populated on load, and so on down the line as the program runs. The issue arises when I want to sort the `itemInfo` objects in the `subItems` array. I'm using LINQ to do this (because there doesn't seem to be any other reasonable way to sort lists of a non-builtin type). So here's what I have: ``` foreach (slotInfo sInf in gAllCats[c].items) { var sortedSubItems = from itemInfo iInf in sInf.subItems orderby iInf.subNum ascending select iInf; IList<itemInfo> sortedSubTemp = new List<itemInfo(); foreach (itemInfo iInf in sortedSubItems) { sortedSubTemp.Add(iInf); } sInf.subItems.Clear(); sInf.subItems = sortedSubTemp; // ERROR: see below } ``` The error is, "Cannot modify members of 'sInf' because it is a 'foreach iteration variable'". a, this restriction makes no sense; isn't that a primary use of the foreach construct? b, (also out of spite) what does Clear() do if not modify the list? (BTW, the List does get cleared, according to the debugger, if I remove the last line and run it.) So I tried to take a different approach, and see if it worked using a regular for loop. (Apparently, this is only allowable because `gAllCats[c].items` is actually an `IList`; I don't think it will allow you to index a regular `List` this way.) ``` for (int s = 0; s < gAllCats[c].items.Count; s++) { var sortedSubItems = from itemInfo iInf in gAllCats[c].items[s].subItems orderby iInf.subNum ascending select iInf; IList<itemInfo> sortedSubTemp = new List<itemInfo>(); foreach (itemInfo iInf in sortedSubItems) { sortedSubTemp.Add(iInf); } //NOTE: the following two lines were incorrect in the original post gAllCats[c].items[s].subItems.Clear(); gAllCats[c].items[s].subItems = sortedSubTemp; // ERROR: see below } ``` This time, the error is, "Cannot modify the return value of 'System.Collections.Generic.IList.this[int]' because it is not a variable." Ugh! What is it, if not a variable? and when did it become a 'return value'? I know there has to be a 'correct' way to do this; I'm coming to this from a C background and I know I could do it in C (albeit with a good bit of manual memory management.) I searched around, and it seems that `ArrayList` has gone out of fashion in favor of generic types (I'm using 3.0) and I can't use an array since the size needs to be dynamic.

Original source