使用Action词典而不是switch语句

时间:2011-08-24 10:12:17

标签: c# refactoring polymorphism conditional-statements

我只是在查看我的一些旧代码(有一些空闲时间),我注意到了一个相当冗长的switch语句。由于获得了新的知识,我已经以下面的形式重构了它:

private Dictionary<string, Action> createView
    {
        get
        {
            return new Dictionary<string, Action>()
            {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
            };
        }
    }

您是否会考虑这种良好做法,或者这仅仅是一个超级丰富且不必要的案例?我渴望确保我学到的新技术,仅仅为了它而不是聪明,并且它们实际上为代码增加了好处。

感谢。

4 个答案:

答案 0 :(得分:18)

长切换语句是一种经典的难闻气味,并且始终是重构的目标。

此处执行的“标准”步骤是Replace Conditional with Polymorphism。这是Martin Fowler的书Refactoring(11年前出版于1999年)中列出的步骤之一。

现在处理像对象这样的函数非常容易(例如使用Action),这可能是一个很好的解决方案。

不,我不认为你为此而聪明。如果我想在将来添加其他选项,我可以很容易地看到需要做什么。

答案 1 :(得分:9)

根据您的应用程序,您可以避免始终构造新的字典对象,但将其声明为类成员,在首次访问时初始化并始终返回相同的实例。但很难说,它是否真的符合您的需求。 像这样我的意思是

public class MyClass 
{
   Dictionary<string, Action> dict = null; 

    private Dictionary<string, Action> createView
    {
        get
        {
            if(dict  == null) 
            {
              dict  = new Dictionary<string, Action>()
              {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
              };
            }

            return dict;
        }
    }

}

修改

概念的角度来看,我用字典swicth/case替换长TryGetValue是一个非常好的解决方案。

希望这会有所帮助......

答案 2 :(得分:5)

这种方法很棒。

我使用的不只是Action。它对滤波器和选择器也非常有效。类似的东西:

var filters = new Dictionary<string, Func<MyEntity, bool>>()
{
    // ...
};

var query = entities.Where(filters["X"]);

答案 3 :(得分:2)

如果代码一经编写,在很大程度上是静态的,不会有太大的变化,那么我就会遇到switch。至少在表面上,你的字典方法很适合于更具动态性 - 这是基于更多的要求。

至于使用这种方法用代码替换各地的交换机,我个人在大多数情况下都不这样做。我的诚实意见是,为了它而只是聪明,但它仍然很容易维护。正如我所见,个人对最佳实践的品味是最重要的因素。

另一方面,正如其他人所说,这可能是长切换语句的可行解决方案。然后,像Strategy Pattern这样的东西也是支持行为变化的好方法。