在代码进行优化的时候,发现了switch case太长,有的竟然长达30个远远超过一屏这样在代码的可读性来说很差。特别在我们看代码的时候要拉下拉框我个人觉得这是不合理的。但是我不建议有switch就进行反射或委托来解决。看实际的情况比喻10个以为还是可以接受的。因为switch看起来更加的直接而且效率相对来说是最好的。那下面就用代码来一点点进行解释

1:传统的用法

1.1:现在我们有一个需求通过传递参数来获取相关的信息。首先我们先看方法

  1. public class SwitchMethod {
  2. public string GetSerialNumber(string serialNumber)
  3. {
  4. return serialNumber;
  5. }
  6.  
  7. public string GetName(string name)
  8. {
  9. return name;
  10. }
  11.  
  12. public string GetAge(string age)
  13. {
  14. return age;
  15. }
  16.  
  17. public string GetBirthday(string birthday)
  18. {
  19. return birthday;
  20. }
  21.  
  22. }

调用的方法

1.2:客户端的调用

  1. string action =Console.ReadLine() ;
  2. var switchMethod=new SwitchMethod();
  3. switch (action)
  4. {
  5. case "serialNumber":
  6. Console.WriteLine(switchMethod.GetSerialNumber(""));
  7. break;
  8. case "name":
  9. Console.WriteLine(switchMethod.GetName("zhangsan"));
  10. break;
  11. case "age":
  12. Console.WriteLine(switchMethod.GetAge(""));
  13. break;
  14. case "birthday":
  15. Console.WriteLine(switchMethod.GetBirthday(""));
  16. break;
  17. }

客户端调用

1.3:效果

以上是我们最常规的用法看起来最直观但是你想过没有如果有30个方法呢你还这样进行switch case吗 50,100个呢所以下面我用委托来代码

2:委托替代switch

上面我又发现一个问题action凌乱,如果太多了就搞不清什么是什么了所以我们加入枚举

2.1:建立枚举

  1. public enum ActionEnum
  2. {
  3. /// <summary>
  4. /// 编号
  5. /// </summary>
  6. SerialNumber = ,
  7. /// <summary>
  8. /// 姓名
  9. /// </summary>
  10. Name = ,
  11. /// <summary>
  12. /// 年龄
  13. /// </summary>
  14. Age = ,
  15. /// <summary>
  16. /// 生日
  17. /// </summary>
  18. Birthday =
  19. }

action枚举

2.2:我采取字典把需要switch的都存起来

  1. private static void LoadDictionary()
  2. {
  3. if (AllDictionary.Count<=)
  4. {
  5. var switchMethod = new SwitchMethod();
  6. AllDictionary.Add(ActionEnum.SerialNumber, switchMethod.GetSerialNumber);
  7. AllDictionary.Add(ActionEnum.Age, switchMethod.GetAge);
  8. AllDictionary.Add(ActionEnum.Birthday, switchMethod.GetBirthday);
  9. AllDictionary.Add(ActionEnum.Name, switchMethod.GetName);
  10. }
  11. }

字典保存

2.3:建立委托(这是比较简单的其实在方法中还可以提取相似的操作放在委托执行)

  1. public static string Exec(string str,Func<string, string> method) {
  2. return method(str);
  3. }

委托

2.4:客户端调用

  1. Console.WriteLine(Exec("", AllDictionary[ActionEnum.Age]));

客户端调用

2.5:效果

3:反射替代switch

3.1建立一个自定义Attribute类(目的是为了附带方法中的信息)

  1. public class MethodAttribute : Attribute
  2. {
  3. public ActionEnum MethodName;
  4.  
  5. public MethodAttribute(ActionEnum methodName)
  6. {
  7. this.MethodName = methodName;
  8. }
  9. }

特性类

3.2:定义一个基类

  1. public class BaseMethod
  2. {
  3. public Hashtable GetMethodAttribute<T>(T t)
  4. {
  5. var hashtable = new Hashtable();
  6. Type type = t.GetType();
  7. foreach (MethodInfo method in type.GetMethods())
  8. {
  9. var methodArray = (MethodAttribute[]) method.GetCustomAttributes(typeof (MethodAttribute), false);
  10. foreach (MethodAttribute actionMethodAttribute in methodArray)
  11. {
  12. ActionEnum actionName = actionMethodAttribute.MethodName;
  13. hashtable.Add(actionName, method);
  14. }
  15. }
  16. return hashtable;
  17. }
  18.  
  19. public string DoAction(ActionEnum actionName,string str) {
  20. Hashtable ht = GetMethodAttribute(this);
  21. string message = ht.Contains(actionName)
  22. ? ((MethodInfo) ht[actionName]).Invoke(this, new object[] {str}).ToString()
  23. : string.Format("{0} 超过范围", actionName);
  24. return message;
  25. }
  26. }

基类

3.3:修改SwitchMethod类并给方法加上特性

  1. public class SwitchMethod : BaseMethod
  2. {
  3. [Method(ActionEnum.SerialNumber)]
  4. public string GetSerialNumber(string serialNumber)
  5. {
  6. return serialNumber;
  7. }
  8.  
  9. [Method(ActionEnum.Name)]
  10. public string GetName(string name)
  11. {
  12. return name;
  13. }
  14.  
  15. [Method(ActionEnum.Age)]
  16. public string GetAge(string age)
  17. {
  18. return age;
  19. }
  20.  
  21. [Method(ActionEnum.Birthday)]
  22. public string GetBirthday(string birthday)
  23. {
  24. return birthday;
  25. }
  26. }

SwitchMethod 类

3.4:客户端调用

  1. string result = new SwitchMethod().DoAction(ActionEnum.SerialNumber,"");

3.5:注释

3.5.1:type.GetMethods():获取这个类中所有的方法包括基类的方法

3.5.2:method.GetCustomAttributes(typeof (MethodAttribute), false):获取这个方法所有关于MethodAttribute类型的自定义特性

3.5.3:MethodInfo:表示对类中方法的访问

3.6:运行效果

三种方式总结

1:传统的用法

优点:简单易读,效率高

缺点:当量很多的时候会造成方法很长,不易维护,可能修改其中某一个case会引起未知的错误

2:委托

优点:使用委托将公有的进行提取,减少代码量

缺点:加入字典后每次添加都需要在字典后手动添加一个子项。总是觉得别扭,效率稍微差点

3:反射

优点:代码量减少,不在考虑内部如何实现,而且符合开闭原则,只需要添加新的方法,其他地方不作修改。维护性强

缺点:很明显这个效率最差(此处并未加入缓存)

第三种方式参考:http://www.cnblogs.com/vipsoft/archive/2012/10/19/2731126.html

用反射或委托优化switch太长的方法的更多相关文章

  1. insert语句太长,有StringBuilder优化一下

    private void btnSave_Click(object sender, RoutedEventArgs e) { if (IsInsert) { //假设日历控件没有选日期,那帮它赋一个当 ...

  2. spark SQL读取ORC文件从Driver启动到开始执行Task(或stage)间隔时间太长(计算Partition时间太长)且产出orc单个文件中stripe个数太多问题解决方案

    1.背景: 控制上游文件个数每天7000个,每个文件大小小于256M,50亿条+,orc格式.查看每个文件的stripe个数,500个左右,查询命令:hdfs fsck viewfs://hadoop ...

  3. java反射机制性能优化

    import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.uti ...

  4. Google IO 2019 Android 太长不看版

    Google I/O 2019, 这里有个playlist是所有Android开发相关的session视频合集: Android & Play at Google I/O 2019 当然啦每个 ...

  5. Asp.Net SignalR 使用记录 技术回炉重造-总纲 动态类型dynamic转换为特定类型T的方案 通过对象方法获取委托_C#反射获取委托_ .net core入门-跨域访问配置

    Asp.Net SignalR 使用记录   工作上遇到一个推送消息的功能的实现.本着面向百度编程的思想.网上百度了一大堆.主要的实现方式是原生的WebSocket,和SignalR,再次写一个关于A ...

  6. C#如何反射出委托的签名,如何使用反射调用委托

    本文阐述C#中如何反射出委托的签名,假如我们有委托FooDelegate定义如下 delegate double FooDelegate (string param, bool condition); ...

  7. URL 路径长度限制(错误:指定的文件或文件夹名称太长)

    本节讨论 URL 的构成.SharePoint 2010 构建 URL 的方式.URL 的编码和加长以及作为其他 URL 中的参数传递的方式. SharePoint URL 的构成 SharePoin ...

  8. paip.数据挖掘--导出词库 清理太长的iptcode

    paip.数据挖掘--导出词库 清理太长的iptcode 原来eng2atian的时候儿,有些cnchar无对眼的atian,走临时使用nonex代替... 而个,要不个那清理给挂了.. #keywo ...

  9. 如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;)。

    1.如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写SQL语句,SQL语句的命令结束符为分号(;). 2.select查询的多个字段之间要用逗号“,”分割,如果查询涉及多个表,那多个表之 ...

随机推荐

  1. spring整合mongo及调用

    spring整合mongo(maven工程下): 1.web.xml文件中配置需要加载的配置文件: <listener> <listener-class>org.springf ...

  2. list详解

    #include <iostream> #include <vector> #include <list> std::list<std::string> ...

  3. VC++使用socket进行TCP、UDP通信实例总结

    1.        两台计算机通信需要协议,通信的两台计算机IP必须唯一 2.        同一个计算机可以进行多个应用程序与其他计算机通信,IP地址唯一,而端口号是区别同一计算机(同一IP)的唯一 ...

  4. [LuoguP1064][Noip2006]金明的预算方案

    金明的预算方案(Link) 题目描述 现在有\(M\)个物品,每一个物品有一个钱数和重要度,并且有一个\(Q\),如果\(Q = 0\),那么该物件可以单独购买,当\(Q != 0\)时,表示若要购买 ...

  5. Linux下Java性能监控

    Linux下Java性能监控 一.JVM堆内存使用监控 获取thread dump的3种方法: 1)使用$JAVA_HOME/bin/jcosole中的MBean,到MBean>com.sun. ...

  6. ubuntu snmp Error: unknown payload OID

    ubuntu snmp Error: unknown payload OID 2013-11-12 15:51:48 标签:ubuntu Error snmp unknown payload OID ...

  7. 8. DBNEWID 工具(使用nid命令修改db name及dbid)

    以下参考自:https://www.2cto.com/database/201305/207860.html Oralce官网:https://docs.oracle.com/cd/E11882_01 ...

  8. iOS 类似微博或朋友圈的信息流

    1.先上图:   image.png   image.png 因为做过了好几次这样的需求,所以这次想到把它拿出来,下次再需要做的时候直接拿过来改改就能用了,节约时间. 2.功能 文字收起和展开,行高自 ...

  9. ABAP术语-V1 Module

    V1 Module 原文;http://www.cnblogs.com/qiangsheng/archive/2008/03/21/1115707.html Function module creat ...

  10. CentOS7.6离线安装JDK1.8

    卸载CentOS自带的openJDK: 查看openJDK命令:rpm -qa|grep java 结果: java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el ...