【问题标题】:How to refactor this huge switch statement?如何重构这个巨大的 switch 语句?
【发布时间】:2012-10-07 06:00:50
【问题描述】:

我继承了一些代码,其中包含一个 500 行的 switch 语句。基本上,它会开启string 任务并执行相应的操作。

从那以后,我将每个 case 语句移到了新类中它们自己的方法中。巨大的 switch 语句仍然存在,但不是内联每个案例的逻辑,而是调用一个方法,所以它更整洁。

问题是这些方法修改了很多不同的东西。 50% 的方法需要传入 0 个参数。大约 40% 需要 5 个参数,剩下的 10% 每个需要 10 个参数。

目前这个工作,但我想让它变得更好。要么去掉 switch 语句,要么以某种方式减少传入参数的数量。

我正在考虑使用将 strings 映射到 Actions 的 Dictionary 来消除整个开关,但这不起作用,因为我使用了很多 ref 参数(原始类型)和没有办法将它们传递给构造函数并让它们稍后被引用修改。

该问题的明显解决方案是将所有 16 个左右的变量放入一个单独的类中并传递它,但其中很多不是很相关,所以它只是用另一个问题替换一个问题(长参数列表与非-内聚数据类)。

想知道是否还有其他方法可以改进此代码。感谢阅读。

【问题讨论】:

  • 你能用反射和接口做点什么吗?
  • @jcolebrand:该应用程序对性能很敏感,并且涉及移动机械。这部分程序是一个瓶颈,所以我想避免反思。不确定界面将如何提供帮助。也许你可以详细说明?
  • 如果没有任何关于 switch 语句的作用以及它与其余代码的关系的上下文,这有点难以响应。切换的条件和动作是否都相关,或者这只是一种应该完全删除的包罗万象的场景?
  • 反射没那么慢
  • 同意@pvanhouten。一段显示 switch 语句和前几个案例的代码可能有助于让我们了解您所拥有的。

标签: c# refactoring switch-statement


【解决方案1】:

由于无法查看任何类型的代码,我能给您的唯一建议是您应该考虑使用SOLID design principles 进行重构并考虑测试。我会尝试为每个逻辑模块(或开关的条件)创建不同的类,通过这些对象的构造函数(而不是作为方法的参数)传递依赖关系,并尝试创建一些可以用来工作的统一接口在一些测试中。您可能希望通过投入工厂来提取这些对象的条件创建。不过听起来很乱。祝你好运。

【讨论】:

    【解决方案2】:

    您可以在委托中使用 ref 参数,但不能使用内置的 Action 或 Func 通用委托。您必须像这样定义自己的:

    public delegate void DelegateWithRefParameters(ref int i, ref long l, ref bool b, ref object o);
    
    public class Program
    {
        public static void Main(string[] args)
        {
            int i = 0;
            long l = 0;
            bool b = false;
            object o = null;
    
            var lookup = new Dictionary<string, DelegateWithRefParameters>() 
            {
                { "object", ModifyObject },
                { "int", ModifyInt },
                { "bool", ModifyBool },
            };
    
            string s = "object";
    
            lookup[s](ref i, ref l, ref b, ref o);
        }
    
        private static void ModifyObject(ref int i, ref long l, ref bool b, ref object o)
        {
            o = new object();
        }
    
        private static void ModifyInt(ref int i, ref long l, ref bool b, ref object o)
        {
            i++;
        }
    
        private static void ModifyBool(ref int i, ref long l, ref bool b, ref object o)
        {
            b = !b;
        }              
    
    }
    

    您只需修改所有方法以使用相同的签名。

    【讨论】:

      【解决方案3】:

      由于您的问题不包含代码,因此答案也不可能。我认为最好的办法是向您指出有史以来最好的软件书籍之一的第 82 页:Refactoring: Improving the Design of Existing Code。

      “面向对象代码最明显的症状之一是它相对缺乏 switch 语句。大多数时候你看到一个 switch 语句你应该考虑多态性。”

      然后他列出了一些用于帮助实现这一目标的特定模式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-05
        相关资源
        最近更新 更多