2

Windows フォーム GroupBox に含まれる特定のラベルにプロパティを設定しようとして、以下のループを記述しました。これは問題なく動作しますが、(不要だと思います) 二重の foreach ネストがあるため、好きではありません。

これをより明確に書き直して、foreach を 1 つだけ使用し、Linq 式を組み合わせて使用​​しようとしましたが、GroupBox から Label へ、またはその逆のいずれかで、実行時に CastException ですべての試みが失敗します。

このループ構成を記述するための、より明確で、より効率的で、より読みやすい方法はありますか?

        foreach (var gb in (from Control c in this.Controls where c is GroupBox select c))
            foreach (Label tlbl in (from Control a in gb.Controls
                                    where a is Label && a.Tag != null && a.Tag.ToString() == "answer"
                                    select a))
                tlbl.ForeColor = (tlbl.Name.Replace("lbl", "") == rb.Name) ? afterSelectColor : beforeSelectColor;

読みやすさは私の最高の目標です。それを念頭に置いて、書き直してみる価値はありますか?

4

2 に答える 2

4

foreachLINQ は副作用を引き起こすことを意図していないため、編集は a で行うことをお勧めします。このような:

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;
}

ここに注意SelectManyしてください。foreachネストされたループはほとんど単なるネストされたループであるため、これがネストされたループを LINQ に変換する方法ですforeach

于 2013-06-14T16:34:45.613 に答える
1
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);

ForEach()このメソッドは LINQ の一部ではないことに注意してください。List<T>クラスのメンバーです。LinQ は機能的な機能であるため、そのメソッドはソース オブジェクトに影響を与えることは想定されていません。そのためForEach()、LINQ にはありません。

編集:

の使用が気に入らない場合はList<T>.ForEach()、次のようにすることもできます。

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);
}

これにより、コードが 2 つのステートメントに分割されますが、他のアプローチに比べて読みやすさが大幅に向上します。

編集2:

これは winforms であるため、コレクションControl.Controlsは ではなくIEnumerable<T>、式の中に を含める必要があります。それを修正しました。IEnumerableOfType<T>SelectMany()

于 2013-06-14T16:34:31.443 に答える