如何让这段代码更干?

时间:2012-06-23 21:56:15

标签: c# dry

假设我们有这些复选框:

  • FooCheckBox
  • BarCheckBox
  • 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

5 个答案:

答案 0 :(得分: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);
});

答案 1 :(得分:6)

您可以使用词典来跟上哪些操作引用哪些复选框。然后你可以做以下事情:

foreach(KeyValuePair<CheckBox, Action> kvp in Dict)
{
    if(kvp.Key.Checked)
        kvp.Value.Invoke();
}

答案 2 :(得分: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);
    }
}

但是你可以对消息部分做一些事情,如果它很简单,我可能会根据本地环境进行一些错误检查。

答案 3 :(得分: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");
        }
}

但我认为有时候不是很干很好。

答案 4 :(得分:0)

我会使用Dictionary创建<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);
        }
    }
}