8

假设我们有这些复选框:

  • FooCheckBox
  • 条形复选框
  • BazCheckBox

还有这些方法:

  • 酒吧
  • 巴兹

我只想在选中相应的复选框时调用每个方法。代码可能如下所示:

void DoWork()
{
    if (FooCheckBox.Checked)
    {
        Foo();
        Console.WriteLine("Foo was called");
    }

    if (BarCheckBox.Checked)
    {
        Bar();
        Console.WriteLine("Bar was called");
    }

    if (BazCheckBox.Checked)
    {
        Baz();
        Console.WriteLine("Baz was called");
    }
}

现在考虑一下,除了 3 个复选框和 3 个方法,您还有更多。您将如何重写上面的代码以使其更加DRY

4

5 回答 5

7

对于您提出的案例,我会说,保持原样;您不想在没有充分理由的情况下过度抽象,因为它会使代码库的可维护性降低。当然,背景很重要,而且最终是一个判断电话。

也就是说,这就是我将如何处理这个问题。创建一个集合,其中每个项目都包含控件和操作委托。然后循环并在每个项目上执行逻辑。

var items = new KeyValuePair<CheckBox, Action>[] {
    new KeyValuePair<CheckBox,Action>(FooCheckBox, Foo),
    new KeyValuePair<CheckBox,Action>(BarCheckBox, Bar),
    new KeyValuePair<CheckBox,Action>(BazCheckBox, Baz)
};

foreach (var item in items)
{
    if (item.Key.Checked) 
    {
        item.Value.Invoke();
        Console.WriteLine("Invoked " + item.Value.Method.Name);
    }
}

或者(可能?)更好地使用 Linq:

items.Where(item => item.Key.Checked).ToList().ForEach(item => new {
    item.Value.Invoke();
    Console.WriteLine("Invoked " + item.Value.Method.Name);
});
于 2012-06-23T22:04:21.857 回答
6

您可以使用字典来了解哪些操作引用了哪些复选框。然后您可以执行以下操作:

foreach(KeyValuePair<CheckBox, Action> kvp in Dict)
{
    if(kvp.Key.Checked)
        kvp.Value.Invoke();
}
于 2012-06-23T22:02:23.273 回答
4

为简单起见,我会选择

void DoWork()
{
    DoIfChecked(FooCheckBox, Foo, "Foo as Called");
    DoIfChecked(BarCheckBox, Bar, "Bar as Called");
    DoIfChecked(BazCheckBox, Baz, "Baz as Called");
}
void DoIfChecked(CheckBox checkBox, Action action, string message)
{
    if (checkBox.IsChecked)
    {
        action();
        Console.WriteLine(message);
    }
}

但是如果消息部分那么简单,您可以对它做一些事情,并且我可能会根据本地上下文进行一些错误检查。

于 2012-06-23T22:13:01.543 回答
2

可以通过以下方式完成:

void DoWork()
{
    Func<Action, string, Tuple<Action, string>> toT = 
        (a, s) => new Tuple<Action, string>(a, s);

    var map = new Dictionary<CheckBox, Tuple<Action, string>>
    {
        {FooCheckBox, toT(Foo, "Foo")},
        {BarCheckBox, toT(Bar, "Bar")},
        {BazCheckBox, toT(Baz, "Baz")},
    };

    foreach (var x in map.Keys)
        if (x.Checked)
        {
            map[x].Item1();
            Console.WriteLine(map[x].Item2 + " was called");
        }
}

但我认为有时不是很干燥是可以的。

于 2012-06-23T22:07:07.893 回答
0

我将创建一个Dictionarywith<CheckBox, Func>并遍历每个值:

Dictionary<CheckBox, Func> checkboxes = new Dictionary<CheckBox, Func>();
void Init()
{
    checkboxes.Add(FooCheckBox, Foo);
    checkboxes.Add(BarCheckBox, Bar);
    checkboxes.Add(BazCheckBox, Baz);
}

void DoWork()
{
    foreach (KeyValuePair<CheckBox, Func> checkbox in checkboxes)
    {
        if (checkbox.Key.Checked)
        {
            checkbox.Value();
            Console.WriteLine("{0} was called", checkbox.Text);
        }
    }
}
于 2012-06-23T22:07:55.773 回答