我最近刚刚遇到了这个问题,搜索这个问题却没有结果......
所以假设我有四个复选框,作为一个例子,我想根据哪些东西随时检查来做某些事情......
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.
答案 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
或查找丢失的一件事是可读性,因为您基本上最终会将复选框值转换为位掩码并根据最终的“魔术”整数值执行操作。当然,如果复选框实际上是编号,那么可能很容易跟踪哪一个是哪一位。但如果名称类似于ApplesCheckBox
,SeedsCheckBox
,SoilCheckBox
,那么您将很难将其与整数位掩码匹配。
你可以通过标志枚举获得一些回复。例如,捎带@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.CheckBox1
到CheckboxActions.CheckBox4
封装。作为奖励,与普通旧版CheckboxActions
相比,您可以获得更多类型安全性({1}}到不同的类和方法。
事实上,在玩这个时,我刚学会了你可以在同一个枚举中引用枚举值。所以你可以完全删除魔术值,上面变成了(并且是的,编译):
int