如何在LINQ中重写C#foreach

Jam*_*mes 1 c# linq

当我构建以下内容时,我收到错误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;
Run Code Online (Sandbox Code Playgroud)

我理解为什么会出现这种错误,但我正在考虑一种巧妙的方法来重写代码.我可以使用嵌套for循环,但有一个很好的LINQ解决方案吗?

(如果它是不明确的,我试图设置ClassId所有时段的所有星期的所有日子clsId,无论在PeriodTypeTimetablePeriod.Types.Registration.)

Cod*_*aos 6

我假设你有struct这样的:

public struct Period
{
    public SomeType ClassId{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

这意味着使用LINQ对集合进行的任何迭代或foreach将对值的副本起作用.因此,如果您修改它们,则只修改临时副本,然后将其丢弃.原始结构将保持不变.

对于这个和许多其他原因,应该避免使用可变结构,除非你有充分的理由使用它们.(搜索"Mutable structs evil",你会发现很多)

在您的情况下,您可以简单地替换struct类.然后,您将获得引用语义.

或者你可以使用for循环,它可以让你直接访问.但它仍然无法用天真的实现进行编译:

for(int i=i;i<list.Count;i++)
  list[i].ClassId=something;
Run Code Online (Sandbox Code Playgroud)

因为列表上的索引器是一个属性,它会复制其结果.对于数组,这将起作用,因为数组的索引器返回托管引用(或类似的东西).对于您需要执行的列表:

for(int i=i;i<list.Count;i++)
{
  var copy=list[i];
  copy.ClassId=something;
  list[i]=copy;
}
Run Code Online (Sandbox Code Playgroud)