如何在LINQ中重写c# foreach

本文关键字:重写 foreach LINQ | 更新日期: 2023-09-27 18:02:15

当我构建以下代码时,我得到了错误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;

我明白为什么会出现这个错误,但是我正在想一个简洁的方法来重写代码。我可以使用嵌套的for循环,但是有一个好的LINQ解决方案吗?

(在不清楚的情况下,我试图将所有星期的所有日子的所有时期的ClassId设置为clsId,无论PeriodTypeTimetablePeriod.Types.Registration。)

如何在LINQ中重写c# foreach

我假设你有一个这样的struct:

public struct Period
{
    public SomeType ClassId{get;set;}
}

这意味着使用LINQ或foreach对集合进行的任何迭代都将在值的副本上工作。因此,如果你修改它们,你只修改了一个临时副本,然后它将被丢弃。原结构体将保持不变。

由于这个原因和许多其他原因,应该避免使用可变结构,除非你有很好的理由使用它们。(搜索"可变结构邪恶",你会发现很多)

在您的情况下,您可以简单地用class替换struct。然后得到引用语义。

或者您可以使用for循环,它可以提供直接访问。但是它仍然不能用幼稚的实现进行编译:

for(int i=i;i<list.Count;i++)
  list[i].ClassId=something;

因为列表上的索引器是一个属性,它复制它的结果。对于数组,这可以工作,因为数组的索引器返回托管引用(或类似的东西)。对于列表,您需要这样做:

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

请尝试以下代码。

您的问题与代码是否为LINQ无关,如@CodeInChaos所提到的。由于pd是Struct类型,您需要替换它来设置值(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, ....);
        }
    }
}