How to rewrite a C# foreach in LINQ
When I build the following, I get the error Cannot modify members of 'pd' because it is a 'foreach iteration variable'
.
foreach (var w in tt.Weeks)
开发者_运维技巧 foreach (var d in w.Days)
foreach (var pd in d.Periods)
if (pd.Type == TimetablePeriod.Types.Registration) pd.ClassId = clsId;
I understand why this error occurs, but I'm trying to think of a neat way to rewrite the code. I could use nested for
loops, but is there a nice LINQ solution?
(In case it's not clear, I'm trying to set the ClassId
of all periods in all days of all weeks to clsId
, wherever the PeriodType
is TimetablePeriod.Types.Registration
.)
I assume you have a struct
like this:
public struct Period
{
public SomeType ClassId{get;set;}
}
This means that any iteration over a collection using either LINQ or foreach
will work on copies of the values. So if you modify them you only modify a temporary copy which will then be discarded. The original struct will remain untouched.
For this and many other reasons mutable structs should be avoided unless you have a really good reason to use them. (Search for "Mutable structs evil" and you'll find a lot)
In your case you can simply replace struct
with class. You then get reference semantics.
Or you can use a for loop, which gives you direct access. But it will still not compile with the naive implementation:
for(int i=i;i<list.Count;i++)
list[i].ClassId=something;
Because the indexer on lists is a property, which copies its results. With arrays this would work since the indexer of an array returns a managed reference(or something similar). For lists you need to do:
for(int i=i;i<list.Count;i++)
{
var copy=list[i];
copy.ClassId=something;
list[i]=copy;
}
Please try the following code.
Your problem is not related to whether the code is LINQ or not as @CodeInChaos mentioned. As pd
is Struct type, you need to replace it to set the value(clsId).
foreach (var w in tt.Weeks)
{
foreach (var d in w.Days)
{
for (int i = 0; i < d.Periods.Count; i++)
{
if (d.Periods[i].Type == TimetablePeriod.Types.Registration)
d.Periods[i] = new Period(clsId, ....);
}
}
}
精彩评论