C# 如何/应该用一个linq查询替换嵌套的foreach?

C# 如何/应该用一个linq查询替换嵌套的foreach?,c#,winforms,linq,foreach,nested,C#,Winforms,Linq,Foreach,Nested,试图在Windows窗体GroupBox中包含的某些标签上设置属性,我编写了下面的循环。这很好,但我不喜欢它,因为它(我认为不必要)有两个foreach嵌套 我试图将其重写得更清楚,只使用一个foreach和一个组合的Linq表达式,但我所有的尝试都在运行时失败,出现了一个CastException,从GroupBox到Label,或者反之亦然 是否有一种更清晰、更高效或更可读的方法来编写此循环构造 可读性是我的最高目标。考虑到这一点,是否值得尝试重写它 Controls.OfType<G

试图在Windows窗体GroupBox中包含的某些标签上设置属性,我编写了下面的循环。这很好,但我不喜欢它,因为它(我认为不必要)有两个foreach嵌套

我试图将其重写得更清楚,只使用一个foreach和一个组合的Linq表达式,但我所有的尝试都在运行时失败,出现了一个CastException,从GroupBox到Label,或者反之亦然

是否有一种更清晰、更高效或更可读的方法来编写此循环构造

可读性是我的最高目标。考虑到这一点,是否值得尝试重写它

Controls.OfType<GroupBox>
        .SelectMany(x => x.Controls.OfType<Label>)
        .Where(x => x.Tag != null && x.Tag.ToString() == "answer")
        .ToList()
        .ForEach(x => x ForeColor = (x.Name.Replace("lbl", "") == rb.Name) ? afterSelectColor : beforeSelectColor);
虽然这将代码分成两条语句,但与其他方法相比,它大大提高了可读性

Edit2:


由于这是winforms,
Control.Controls
集合不是一个
IEnumerable
,而是一个
IEnumerable
,因此类型的
必须包含在
SelectMany()
表达式中。更正了。

我建议您在
foreach
中进行编辑,因为LINQ不会引起副作用。像这样:

foreach (Label tlbl in (this.Controls.OfType<GroupBox>()
    .SelectMany(g => g.Controls.Cast<Control>()).OfType<Label>()
    .Where(a => a.Tag != null && a.Tag.ToString() == "answer")))
{
    tblb.ForeColour = tlbl.Name.Replace("lbl", "") == rb.Name ? afterSelectColor : beforeSelectColor;
}
foreach(标签tlblin(this.Controls.OfType())
.SelectMany(g=>g.Controls.Cast())。of type()
.Where(a=>a.Tag!=null&&a.Tag.ToString()
{
tblb.ForeColour=tlbl.Name.Replace(“lbl”和“”)==rb.Name?afterSelectColor:beforeSelectColor;
}

注意
在此处选择many
。这就是将嵌套的
foreach
循环转换为LINQ的方法,因为它几乎只是一个嵌套的
foreach
循环。

遗漏了很多,但几乎没有。LINQ的拼写与前面一样,而不是LINQ。答案很好。但我觉得这是最具可读性的,而且没有Eric Lippert建议的副作用。谢谢我应该先试试。这不会编译,因为“无法从用法推断方法SelectMany的类型参数。请尝试显式指定类型参数。”@shipr这是我的错误,现已修复。哎哟^^'@newStackExchangeInstance您的代码未编译请参见我的编辑。@HighCore修复了另一个错误。我以前从未使用过winforms,这就是我不知道的原因。
var labels = Controls.OfType<GroupBox>
                     .SelectMany(x => x.Controls.OfType<Label>)
                     .Where(x => x.Tag != null && x.Tag.ToString() == "answer")

foreach (var label in labels)
{
  label.ForeColor = (label.Name.Replace("lbl", "") == rb.Name) ? afterSelectColor : beforeSelectColor);
}
foreach (Label tlbl in (this.Controls.OfType<GroupBox>()
    .SelectMany(g => g.Controls.Cast<Control>()).OfType<Label>()
    .Where(a => a.Tag != null && a.Tag.ToString() == "answer")))
{
    tblb.ForeColour = tlbl.Name.Replace("lbl", "") == rb.Name ? afterSelectColor : beforeSelectColor;
}