是否有更有效的方法来检查复选框?

时间:2015-09-07 10:40:12

标签: 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 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;
}

他们还需要随时检查其中一个复选框,因为每个复选框的checkchanged事件都会调用此代码:

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

所以,我的问题是...... 是否有更好的(或者更有效,或者可以减少代码行)的方式根据哪个复选框/复选框进行检查?或者我们是否真的坚持这种方法(或这种方法的变体)?

请注意,对于此示例,无论您根据选中的复选框执行的操作...都不能简单地“添加”或“附加”。

还应该注意的是,开关盒方法与这种方法大致相同......所以它很可能没有什么区别。它也是concluded elsewhere that if-statements are more efficient that switch-case.

2 个答案:

答案 0 :(得分:3)

您可以创建一个字典映射int s到Action s或Func s(或其他任何合适的),然后使用复选框设置整数位。一旦计算出整数,就可以在字典中查找并调度到该方法。字典可以初始化一次。

E.g。

int option = 0;
if(CB1.Checked) option = option | 1;
if(CB2.Checked) option = option | 2;
if(CB3.Checked) option = option | 4;
if(CB4.Checked) option = option | 8;

if(!lookup.HasKey(option))
    throw new NotSupportedException("I didn't expect that combination of options");

lookup[option]();

lookup之前已经初始化的地方(可能它是该班级的static成员)

lookup = new Dictionary<int,Action>();
lookup.Add(0,DoNothingNoOptionsSet);
lookup.Add(1,DoJustCB1);
lookup.Add(2,DoJustCB2);
lookup.Add(3,DoCB1AndCB2ButNeverCB4);
/* etc, for other valid options */

这也使您有机会将描述性名称应用于执行的每个函数,将它们移动到单独的函数中,然后将 常用功能的区域组合到较小的辅助函数中

答案 1 :(得分:2)

我不确定你能做多少分支机构。如果逻辑允许,您可以通过嵌套if语句来处理其中的一些。但这仅在某些情况下有用,而在其他情况下则更糟糕。

如果您真正拥有16个不同的,不相关的4个复选框选项,最好使用switch或查找词典,如@Damien_The_Unbeliever建议的那样。使用switch或查找丢失的一件事是可读性,因为您基本上最终会将复选框值转换为位掩码并根据最终的“魔术”整数值执行操作。当然,如果复选框实际上是编号,那么可能很容易跟踪哪一个是哪一位。但如果名称类似于ApplesCheckBoxSeedsCheckBoxSoilCheckBox,那么您将很难将其与整数位掩码匹配。

你可以通过标志枚举获得一些回复。例如,捎带@Damien_The_Unbeliever's answer

[Flags]
enum CheckboxActions
{
    None = 0,

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

    DoJustCB1 = 1,
    DoJustCB2 = 2,
    DoCB1AndCB2ButNeverCB4 = 3
}

然后,

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

或者只需设置Dictionary<CheckboxActions, Action>并将其用作查找。

您可以为枚举值使用适当的名称,以便准确了解正在发生的事情,并且复选框的顺序由枚举值CheckboxActions.CheckBox1CheckboxActions.CheckBox4封装。作为奖励,与普通旧版CheckboxActions相比,您可以获得更多类型安全性({1}}到不同的类和方法。

事实上,在玩这个时,我刚学会了你可以在同一个枚举中引用枚举值。所以你可以完全删除魔术值,上面变成了(并且是的,编译):

int