【问题标题】:Is it possible to combine all of these into one foreach?是否可以将所有这些组合到一个 foreach 中?
【发布时间】:2017-11-06 11:37:42
【问题描述】:

到目前为止,我已经尝试了 var 并且无法使其工作。 代码:

var a = new { drives1, ipAdd1, spotify1, timeAndDate1, activeWindow1, reminders11, weather1 };

然后 foreach (Control/var c in a) 并得到错误,我确信必须有一个简单的方法,而不需要下面的所有代码。


当前代码:

        foreach (Control c in drives1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in ipAdd1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in spotify1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in timeAndDate1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in activeWindow1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in reminders11.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
        foreach (Control c in weather1.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }

【问题讨论】:

  • 你可以做一个 Lambda 表达式,删除循环。但是您需要为每个不同的对象创建一个表达式。您可以将表达式放在一个方法中,然后将每个控件对象传递给该方法。那么这将减少代码重复。
  • 您在使用 Winforms 吗?所有对象都是什么类型:drives1, ipAdd1, spotify1, timeAndDate1,...?
  • @MongZhu:另外,他们有共同的父母吗?
  • 它们都是 UserControl 的,但由于我将它们添加到 Winforms 的方式,它没有显示在 UserConrol 下
  • 在远离控件本身的地方控制这种逻辑似乎很奇怪。问问自己该逻辑是否属于您要放置的地方可能是个好主意。

标签: c# foreach controls parallel-foreach


【解决方案1】:

至少你可以让它与 2 个 foreach 一起工作:

var a = new List<ContainerControl> { drives1, ipAdd1, spotify1, timeAndDate1, activeWindow1, reminders11, weather1 };
foreach (var container in a) {
    foreach (Control c in container.Controls)
    {
        if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
    }
}

【讨论】:

  • 您正在初始化一个无法迭代的匿名对象。您在此处发布的代码将无法编译。
  • 感谢您指出。我的意思是它是 List 类型,但没有更改代码。我现在就修。
  • 这段代码是最好的,很好很简短感谢您的帮助,标记为正确:) 再次感谢您。
  • 感谢@TimothyGroote 以及指出我最初的错误:)
  • 还支持@Mong Zhu 指出集合初始化程序允许您这样做!
【解决方案2】:

如果a 中的所有项目都有一个定义Controls 的公共超类,那么您可以聚合所有控件,过滤您需要的控件,然后对其进行迭代:

var allControls = a.SelectMany(i=>i.Controls.Where(c=>c.Name.StartsWith("SC"));

foreach (var control in allControls)
{
    c.ForeColor = Color.FromArgb(rr, gg, bb);
}

如果没有,那么你可以使用union

var allControls = drives1.Controls
    .Union(ipAdd1.Controls)
    .Union(spotify1.Controls)
    .Union ...
    .Where(c=>c.Name.StartsWith("SC");

【讨论】:

    【解决方案3】:

    都是UserControl的,

    然后创建一个List&lt;UserControl&gt; 作为集合。这样您指定通用数据类型,编译器不会抱怨。然后它将循环遍历它:

    List<UserControl> a = new List<UserControl>{ drives1, ipAdd1, spotify1, timeAndDate1, activeWindow1, reminders11, weather1 };
    
    foreach (UserControl uc in a)
    {
        foreach (Control c in uc.Controls)
        {
            if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
        }
    }
    

    解释:

    如果你查看documentation 中类UserControl 的继承层次结构

    您会发现它上面的 2 个级别继承自 Control 类,该类具有您在循环中使用的属性 Controls。所以UserControl 是您可以用于收藏的最低共同祖先。

    【讨论】:

    • 您的示例中的列表初始化是否像那样工作? (也就是说,它真的不是List&lt;List&lt;UserControl&gt;&gt;)吗?
    • @TimothyGroote 是的,它确实如此,代码编译并工作,只是再次测试它以确保
    【解决方案4】:

    添加方法:

    private void SetColor( List<Control> control)
    {
        foreach (Control c in control)
        {
           if (c.Name.StartsWith("SC")) { c.ForeColor = Color.FromArgb(rr, gg, bb); }
         }
    }
    

    遍历一个:

    foreach (Control c in a)
    {
       SetColor(c);
    }
    

    【讨论】:

    • 您可以使用 linq 将第一个代码示例中的 if 语句移动到 foreach 选择器中
    【解决方案5】:

    你可以这样做

    private static void Edit()
    {
    
       setForeColor(drives1.Controls);
       setForeColor(ipAdd1.Controls);
       setForeColor(spotify1.Controls);
       setForeColor(timeAndDate1.Controls);
       setForeColor(activeWindow1.Controls);
       setForeColor(reminders11.Controls);
       setForeColor(weather1.Controls);
    
    }
    
    
    private static void setForeColor(Controls controls)
    {
            foreach (Control c in controls)
            {
                if (c.Name.StartsWith("SC"))
                { 
                    c.ForeColor = Color.FromArgb(rr, gg, bb); 
                }
            }
    
    }
    

    【讨论】:

    • 我发现这可以通过一些调整来工作,这个下面的帖子效果最好,行数更少,不过谢谢你的帮助:)
    【解决方案6】:

    您可以将它们加入到单个 IEnumerable 中,然后使用 where 条件来获取匹配器:

    namespace ConsoleApp1 {
    
        public class Control {
            public Control(string name) {
                this.Name = name;
            }
    
            public string Name { get; set; }
        }
    
        class Program {
            static void Main(string[] args) {
                var list1 = new List<Control> { new Control("a"), new Control("b"), new Control("c") };
                var list2 = new List<Control> { new Control("a"), new Control("b"), new Control("c") };
                var list3 = new List<Control> { new Control("a"), new Control("b"), new Control("c") };
    
                foreach (var ctrl in GetList(list1, list2, list3).Where(c => c.Name.StartsWith("a"))) {
                    ctrl.ForeColor = Color.FromArgb(rr, gg, bb);
                }
            }
    
            private static IEnumerable<Control> GetList (params IEnumerable<Control>[] controls) {
                return controls.SelectMany(x => x);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      相关资源
      最近更新 更多