C# 是否有一种更有效的方法根据选中的复选框进行操作?

C# 是否有一种更有效的方法根据选中的复选框进行操作?,c#,winforms,performance,checkbox,.net-4.0,C#,Winforms,Performance,Checkbox,.net 4.0,我最近也遇到了这个问题,搜索这个问题还没有结果 比如说,我有四个复选框,我想根据它们中的哪一个在任何时候被选中来做一些事情 if (CB1.Checked) { //Do things here if only checkbox 1 is checked. } else if (CB2.Checked) { //Do things here if only checkbox 2 is checked. } else if (CB3.Checked) { //Do thin

我最近也遇到了这个问题,搜索这个问题还没有结果

比如说,我有四个复选框,我想根据它们中的哪一个在任何时候被选中来做一些事情

if (CB1.Checked)
{
    //Do things here if only checkbox 1 is checked.
}
else if (CB2.Checked)
{
    //Do things here if only checkbox 2 is checked.
}
else if (CB3.Checked)
{
    //Do things here if only checkbox 3 is checked.
}
else //if (CB4.Checked)
{
    //Do things here if only checkbox 4 is checked.
}
我相信大多数人都会倾向于使用上面的示例代码片段,或其变体。看起来很简单,对吧?但是如果。。。你不是只检查一个复选框吗

if (CB1.Checked && CB2.Checked)
{
    //Do things here if only checkbox 1 & 2 is checked.
}
else if (CB2.Checked && CB3.Checked)
{
    //Do things here if only checkbox 2 & 3 is checked.
}
else if (CB3.Checked && CB1.Checked)
{
    //Do things here if only checkbox 3 & 1 is checked.
}
else if (CB4.Checked && CB1.Checked)
{
    //Do things here if only checkbox 4 & 1 is checked.
}
else if (CB4.Checked && CB2.Checked)
{
    //Do things here if only checkbox 4 & 2 is checked.
}
else //if (CB4.Checked && CB3.Checked)
{
    //Do things here if only checkbox 4 & 3 is checked.
}
可以看出。。。if-else语句的数量已增加。。。如果你想比较比4更多的复选框,或者在4个复选框中比较更多的复选框,它会的。。。这可能会使事情复杂化,因为(很可能)大多数程序员都无法避免它

我还应该提到,由于以下代码,我知道在给定时间选中了多少复选框:

private int GetNumberOfCheckboxesChecked()
{
    int NumberofCheckBoxesChecked = 0;
    foreach (Control c in groupBox1.Controls)
    {
        if ((c is CheckBox) && ((CheckBox)c).Checked)
            NumberofCheckBoxesChecked++;
    }

    return NumberofCheckBoxesChecked;
}
private void OneAtLeast(object originalSender)
{
    CheckBox tempCB = (CheckBox)originalSender;
    if (!CB1.Checked && !CB2.Checked && !CB3.Checked && !CB4.Checked)
    {
        tempCB.Checked = true;
        MessageBox.Show("You must select at least one option!", "Invalid Operation", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
他们还需要始终选中其中一个复选框,因为每个复选框的checkchanged事件调用以下代码:

private int GetNumberOfCheckboxesChecked()
{
    int NumberofCheckBoxesChecked = 0;
    foreach (Control c in groupBox1.Controls)
    {
        if ((c is CheckBox) && ((CheckBox)c).Checked)
            NumberofCheckBoxesChecked++;
    }

    return NumberofCheckBoxesChecked;
}
private void OneAtLeast(object originalSender)
{
    CheckBox tempCB = (CheckBox)originalSender;
    if (!CB1.Checked && !CB2.Checked && !CB3.Checked && !CB4.Checked)
    {
        tempCB.Checked = true;
        MessageBox.Show("You must select at least one option!", "Invalid Operation", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
因此,我的问题是……是否有更好的(或更有效的,或可以减少代码行数)方法根据选中的复选框来做事情?或者我们真的坚持这种方法(或者这种方法的变体)

请注意,在本例中,无论您根据选中的复选框执行什么操作。。。不能简单地“添加”或“附加”。


还应注意的是,开关箱方法或多或少与此方法相同。。。所以这很可能不会有什么不同。它还被

您可以创建一个字典映射,将
int
s映射到
Action
s或
Func
s(或任何其他合适的),然后使用复选框设置整数中的位。计算完整数后,在字典中查找并分派给该方法。这本词典可以草签一次

例如

其中,
lookup
先前已初始化(可能是类的
静态成员)

lookup=newdictionary();
lookup.Add(0,donothingNoOptions集);
添加(1,DoJustCB1);
添加(2,DoJustCB2);
查找.添加(3,docb1和cb2butnevercb4);
/*等,以获取其他有效选项*/

这也让您有机会对执行的每个函数应用描述性名称,将它们移出到单独的函数中,然后将具有公共功能的区域合并到较小的辅助函数中。

我不确定您能对分支的数量做多少。如果逻辑允许,您可以通过嵌套
If
语句来处理其中的一些问题。但这只在某些情况下有用,而在另一些情况下更糟

如果你的4个复选框中确实有16个不同的、不相关的选项,那么最好使用
开关,或者不信者建议的@Damien\u查找字典。使用
开关
或查找时丢失的一件事是可读性,因为您基本上会将复选框值转换为位掩码,并根据最终的“神奇”整数值执行操作。当然,如果复选框实际上是按照您的方式编号的,那么很容易跟踪哪一个是哪一位。但如果名称类似于
ApplesCheckBox
SeedsCheckBox
SoilCheckBox
,则很难将其与整数位掩码匹配

您可以通过flags枚举获得其中的一部分。例如,背负:

那么

要使用它,例如在交换机中:

switch (option)
{
    case CheckboxActions.None:
        DoNothingNoOptionsSet();
        break;
    case CheckBoxActions.DoJustCB1:
        DoJustCB1();
        break;
    case CheckBoxActions.DoJustCB2:
        DoJustCB2();
        break;
    case CheckBoxActions.DoCB1AndCB2ButNeverCB4:
        DoCB1AndCB2ButNeverCB4();
        break;
}
或者只需设置一个
字典
,并将其用作查找

您可以为枚举值使用适当的名称,这样您就可以确切地知道发生了什么,并且复选框的顺序由枚举值
CheckboxActions.CheckBox1
CheckboxActions.CheckBox4
封装。作为奖励,与普通的
int
相比,将
CheckboxActions
传递给不同的类和方法会获得更多的类型安全性


事实上,在玩这个游戏时,我刚刚了解到可以从同一个枚举中引用枚举值。因此,您可以完全删除魔法值,上述内容将变为(是的,这将编译):


这是一个好问题,但您是否有更具体的用例?复选框的值如何相互作用?我发现很难相信根据4个复选框的值,您有16个完全不同的选项。请注意:您提供的代码将无法工作。对于每个条件,您都需要这样的设置:
(CB1.Checked&&CB2.Checked&&CB3.Checked&&CB4.Checked)
,否则您将得到错误的结果。我想说,复选框的值实际上没有太多交互作用。但它对其他组合的作用却大不相同。不过,这个场景并没有涉及数学。@Ulric true,我在写问题时漏掉了这个,对不起!编辑:添加了一段最有可能相关的代码,可能有助于修复该问题。@Kaitlyn无需道歉。如果我们是完美的,那么我们可能会得到更好的报酬这不就是有效地抽象出一个switch语句,并将其移动到与当前方法无关的初始化代码中吗?除非您计划从多个位置执行相同的操作,否则仅使用
开关(选项)
?@lc会有什么好处?鉴于目前考虑的组合数量(16)以及将来可能更多,我还是希望将代码移到单独的方法中。因此,我还简化了创建一个
开关
,然后在每个分支中只调用一个函数。所有组合都是预期的,并且是允许的,尽管它们都会导致不同的操作。他们也不允许保留任何未选中的复选框
var option = CheckboxActions.None;

if(CB1.Checked) option = option | CheckboxActions.CheckBox1;
if(CB2.Checked) option = option | CheckboxActions.CheckBox2;
if(CB3.Checked) option = option | CheckboxActions.CheckBox3;
if(CB4.Checked) option = option | CheckboxActions.CheckBox4;
switch (option)
{
    case CheckboxActions.None:
        DoNothingNoOptionsSet();
        break;
    case CheckBoxActions.DoJustCB1:
        DoJustCB1();
        break;
    case CheckBoxActions.DoJustCB2:
        DoJustCB2();
        break;
    case CheckBoxActions.DoCB1AndCB2ButNeverCB4:
        DoCB1AndCB2ButNeverCB4();
        break;
}
[Flags]
enum CheckboxActions
{
    None = 0,

    CheckBox1 = 1,
    CheckBox2 = 2,
    CheckBox3 = 4,
    CheckBox4 = 8,

    DoJustCB1 = CheckboxActions.CheckBox1,
    DoJustCB2 = CheckboxActions.CheckBox2,
    DoCB1AndCB2ButNeverCB4 = CheckboxActions.CheckBox1 | CheckboxActions.CheckBox2
}