开发者

How to rewrite a C# foreach in LINQ

开发者 https://www.devze.com 2023-03-20 18:02 出处:网络
When I build the following, I get the error Cannot modify members of \'pd\' because it is a \'foreach iteration variable\'.

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, ....);
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消