c# 过多的if分支如何重构

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# 过多的if分支如何重构相关的知识,希望对你有一定的参考价值。

参考技术A

这个问题问的好。可以用类的方式重构。

比如以下示例

getOrder()

object obj;
if(obj.condition1)

if(obj.condition2)

....

网上抄了一段代码,我注释下。


   public class Client //If分支变成了一个类pipeline,里面是一个list。保存了所有的condition. 它的方法processOrder()会循环执行list中的所有条件。
     
       public void getOrder(string orderNo) 
        
           var order = new Repo().getOrder(orderNo); 
           var pipeline = new Pipeline(); 
           var handle1 = new condition1_Handle(); 
           var handle2 = new condition2_Handle(); 
           pipeline.add_order(order); 
           pipeline.add_handle(handle1); 
           pipeline.add_handle(handle2); 
           pipeline.processOrder(); 
        
    
   class Pipeline 
    
       private List<IHandle> _handles; 
       private string _order; 
       public Pipeline() 
        _handles = new List<IHandle>();  
       internal void add_order(string order) 
        
           this._order = order; 
        
 
       internal void add_handle(IHandle handle1) 
        
           _handles.Add(handle1); 
        
 
       internal void processOrder() 
        
           foreach (var h in _handles) 
            
               h.process(_order); 
            
        
    
   public interface IHandle //定义这个接口只是为了一个规范。
    
       void process(string order); 
    
   public class condition1_Handle : IHandle //然后,用所有的条件分支继承这个接口
    
       public  void process(string _order) 
        
           throw new NotImplementedException(); 
        
    
   public class condition2_Handle : IHandle 
    
       public void process(string _order) 
        
           throw new NotImplementedException(); 
        
   

http://virusswb.blog.51cto.com/115214/1081790

编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支

 

建议149:使用表驱动法避免过长的if和switch分支

随着代码变得复杂,我们很容易被过长的if和switch分支困扰。

一个类枚举类型Week如下:

    enum Week
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    }

 如果要把Week的元素值用中文输出,简单而丑陋的方法也许是封装一个GetChineseWeek方法:

        static string GetChineseWeek(Week week)
        {
            switch (week)
            {
                case Week.Monday:
                    return "星期一";
                case Week.Tuesday:
                    return "星期二";
                case Week.Wednesday:
                    return "星期三";
                case Week.Thursday:
                    return "星期四";
                case Week.Friday:
                    return "星期五";
                case Week.Saturday:
                    return "星期六";
                case Week.Sunday:
                    return "星期日";
                default:
                    throw new ArgumentOutOfRangeException("week","星期值超出范围");
            }
        }

 

 之所以说这种方法太丑陋,是因为:

1)分支太长了,而且出现了重复代码。

2)不利于扩展。如果出现星期八、星期九怎么办?当然,星期制已经是固定的了,应该不会出现扩展情况。但是,换种情景来考虑,假设我们正在渲染动画怎么办?谁知道下一秒美工会提交我多少个动画呢?

一种解决方案是使用多态,它很好的符合了“开闭”原则。如果增加条件分支,不必修改源代码,直接增加子类就可以了。利用多态避免分支,这里暂且不表,本建议要采用的是“表驱动法”。

可以把表驱动简单理解为查字典。代码如下表示:

        static string GetChineseWeek(Week week)
        {
            string[] chineseWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
            return chineseWeek[(int) week];
        }

        static void Main(string[] args)
        {
            Console.WriteLine(GetChineseWeek(Week.Friday));
        }

 这是一种按照索引值驱动的表驱动法。枚举元素代表的整型值,很容易和字符串数组索引结合起来,用两行语句就解决了GetChineseWeek方法。但是,这种方法有局限性,如果需要换成:星期一Mike打扫卫生、星期二Rose清理衣柜、星期三Mike和Rose没事可以吵吵架、星期四Rose要去Shopping,也就是说需求由静态属性变成了动态行为,那么事情就变得复杂了。

遇上这种情况,我们可能会想到使用多态,在这里依然使用表驱动法加上一点反射来实现这类动态的行为,代码如下:

    class Program
    {
        static string ActionInTable(Week week)
        {
            string[] methods = { "Cleaning", "CleanCloset", "Quarrel", "Shopping", "Temp", "Temp", "Temp" };
            return methods[(int)week];
        }

        static void Main(string[] args)
        {
            SampleClass sample=new SampleClass();
            var addMethod = typeof (SampleClass).GetMethod(ActionInTable(Week.Monday));
            addMethod.Invoke(sample, null);
        }
    }

    class SampleClass
    {
        public void Cleaning()
        {
            Console.WriteLine("打扫");
        }
        public void CleanCloset()
        {
            Console.WriteLine("整理衣橱");
        }
        public void Quarrel()
        {
            Console.WriteLine("吵架");
        }
        public void Shopping()
        {
            Console.WriteLine("购物");
        }
        public void Temp()
        {
            Console.WriteLine("临时安排");
        }
    }

表驱动法是一种设计思路,也可以称为模式。在实际编码中,不应局限于用索引去驱动行为,而应当根据实际情况灵活运用。

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

以上是关于c# 过多的if分支如何重构的主要内容,如果未能解决你的问题,请参考以下文章

c#基础语句——分支语句的应用

使用 react-navigation 重构 - 使用分支时如何提升静态导航标题?

编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支

C#中的分支结构与循环

C#语句及案例

javascript 从Medium Article重构的重构分支方法