是否有一种更有效的方法来根据复选框被选中来做事情
本文关键字:复选框 方法 一种 有效 是否 | 更新日期: 2023-09-27 18:11:27
我自己最近也遇到了这个问题,搜索这个问题还没有结果…
假设我有四个复选框,作为一个例子,我想根据它们中的哪个在任何时候都被选中来做某些事情…
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个复选框中的更多复选框。这可能会使事情复杂化,(可能)大多数程序员无法避免它。
我还应该提到,我知道在给定的时间有多少复选框被选中,这要归功于这段代码: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);
}
}
所以,我的问题是……是否有更好的(或更有效的,或可以减少代码行)的方式来做事情根据哪个复选框/复选框被选中?还是我们真的坚持这种方法(或这种方法的变体)?
请注意,在这个例子中,无论你要做什么,根据哪个复选框被选中…
还应该注意的是,switch-case方法将或多或少与此方法相同…所以很可能不会有什么不同。在其他地方也得出结论,if语句比switch-case更有效。
您可以创建一个字典,将int
s映射到Action
s或Func
s(或任何其他合适的),然后使用复选框在整数中设置位。一旦计算出整数,就在字典中查找它并分派给该方法。字典只能初始化一次。
。
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 */
这也使您有机会对执行的每个函数应用描述性名称,将它们移出到单独的函数中,然后将是公共功能的区域组合为更小的辅助函数。
我不确定你能对分支的数量做多少。如果逻辑允许,可以通过嵌套if
语句来处理其中的一些问题。但这只在某些情况下有用,在其他情况下会使事情变得更糟。
如果你真的有16个不同的,不相关的4个复选框选项,你最好使用switch
,或查找字典@Damien_The_Unbeliever建议。switch
或查找丢失的一件事是可读性,因为您基本上最终将复选框值转换为位掩码,并根据最终的"魔法"整数值执行操作。当然,如果复选框实际上是编号的,那么跟踪哪个是哪个位可能很容易。但是,如果名称是ApplesCheckBox
, SeedsCheckBox
, SoilCheckBox
之类的,那么您将很难将其与整数位掩码匹配。
您可以使用flags枚举返回其中的一部分。例如,借用@Damien_The_Unbeliever的答案:
[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
封装。作为奖励,与使用普通的旧int
相比,将CheckboxActions
传递给不同的类和方法可以获得更多的类型安全性。
实际上,在这个过程中,我刚刚了解到可以从同一枚举中引用枚举值。因此,您可以完全删除魔术值,上面的代码变成(是的,这可以编译):
[Flags]
enum CheckboxActions
{
None = 0,
CheckBox1 = 1,
CheckBox2 = 2,
CheckBox3 = 4,
CheckBox4 = 8,
DoJustCB1 = CheckboxActions.CheckBox1,
DoJustCB2 = CheckboxActions.CheckBox2,
DoCB1AndCB2ButNeverCB4 = CheckboxActions.CheckBox1 | CheckboxActions.CheckBox2
}