【问题标题】:Using Action dictionaries instead of switch statements使用 Action 字典而不是 switch 语句
【发布时间】:2011-11-02 16:15:18
【问题描述】:

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

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

你会考虑这种好的做法,还是这只是一个多余和不必要的例子?我热衷于确保我学习的新技术不会仅仅为了它而变得聪明,并且它们实际上为代码增加了好处。

谢谢。

【问题讨论】:

    标签: c# refactoring polymorphism conditional-statements


    【解决方案1】:

    长 switch 语句是一种典型的恶臭,并且始终是重构的目标。

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

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

    不,我不认为你是为了聪明而聪明。如果我以后想添加另一个选项,我可以很容易地看到需要做什么。

    【讨论】:

    • +1 感谢您的链接,我以前从未遇到过该重构目录 - 我会读一读。
    • 我以为这不是我要找的答案,但仔细想想,它确实是。我有一个自动生成的文件,其中包含数千个开关案例,每个案例都执行一个方法。它用于 Unity 引擎的可序列化事件系统。现在我有数千个类继承了一个抽象类,其中包含一个 Invoke 虚函数和一个包含它们的字典来替换开关。现在调用者可以缓存从字典中获取的继承类并调用它的虚函数,而不是每次调用都经过一个开关。
    【解决方案2】:

    如果代码在编写后基本上是静态的并且不会进行太多更改,那么我会坚持使用switch。至少从表面上看,您在这里的字典方法非常适合更具动态性-尽管这是基于更多要求的。

    至于使用这种方法用代码替换所有地方的开关,我个人在大多数情况下不会这样做。我的诚实意见是,这只是为了聪明,但它仍然很容易维护。在我看来,个人品味高于最佳实践是最大的因素。

    另一方面,正如其他人所说,这可能是长 switch 语句的可行解决方案。再说一次,Strategy Pattern 之类的东西也是支持行为变化的好方法。

    【讨论】:

      【解决方案3】:

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

      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;
              }
          }
      
      }
      

      编辑

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

      希望对你有帮助……

      【讨论】:

        【解决方案4】:

        这种方法非常好。

        我不仅仅将它与Action 一起使用。它对过滤器和选择器也非常有效。比如:

        var filters = new Dictionary<string, Func<MyEntity, bool>>()
        {
            // ...
        };
        
        var query = entities.Where(filters["X"]);
        

        【讨论】:

        • 这也是一个好方法。学习了该语言的基础知识后,我现在对学习更多复杂部分感到更加自在,发现这些小技巧很有趣:)
        猜你喜欢
        • 2012-11-03
        • 1970-01-01
        • 2020-10-02
        • 2020-06-04
        • 2013-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多