【问题标题】:How to clean up if else seriesif else 系列如何清理
【发布时间】:2017-02-28 09:46:46
【问题描述】:

在C#中工作,想减少if else系列,实体有两个属性FromServiceIDToServiceID,假设我的ServiceClass实例有波纹管信息。如何清理波纹管代码?任何类型的建议都可以接受。

entity= new ServiceClass();
entity.FromServiceID=3
entity.ToServiceID=1

if (entity.FromServiceID == 1)
{
    entity.1KWithdrawal();
}
else if (entity.FromServiceID == 2)
{
    entity.10KWithdrawal();
}
else if (entity.FromServiceID == 3)
{
    entity.BTWithdrawal();
}           
if (entity.ToServiceID == 1)
{
    entity.1KDeposit();
}
else if (entity.ToServiceID == 2)
{
    entity.10KDeposit();
}
else if (entity.ToServiceID == 3)
{
    entity.BTDeposit();
}


public class ServiceClass
{ 

    public int FromServiceID { get; set; }
    public int ToServiceID { get; set; }

    public void 1KWithdrawal()
    { Console.WriteLine("One_KWithdrawal"); }

    public void 10KWithdrawal()
    { Console.WriteLine("Ten_KWithdrawal"); }

    public void BTWithdrawal()
    { Console.WriteLine("BTWithdrawal"); }

    public void 1KDeposit()
    { Console.WriteLine("One_KDeposit"); }

    public void 10KDeposit()
    { Console.WriteLine("Ten_KDeposit"); }

    public void BTDeposit()
    { Console.WriteLine("Ten_KDeposit"); }
}

【问题讨论】:

  • 改用switch ... case ...
  • 那是伪代码吗?您正在初始化对象,但没有将实例分配给变量,因此它们已准备好在初始化后立即被垃圾回收。
  • 类名什么时候可以以数字开头?
  • 如果我们不知道这个类的用途和这些方法的作用,我们将无能为力。它太抽象而无法提供真正的改进。通常我建议将逻辑封装在ServiceClass 中。所以实现一个方法Process(或其他),它根据属性的值调用方法。那么你只需要entity.Process();
  • 标识符(如方法名或类型名)不能以数字开头,所以1KWithdrawal();不能是真实代码。

标签: c# coding-style


【解决方案1】:

使用Dictionary。像这样的:

Dictionary<int, ServiceClass> dictionary = new Dictionary<int, ServiceClass>()
{
    {1,  new ServiceClass()},
    {2,  new ServiceClass()},
    {3,  new BTWithdrawal()},//assume BTWithdrawal inherits from ServiceClass
};

一个如何使用它的例子:

ServiceClass value=new ServiceClass();
value.FromServiceId=1;
value.ToServiceId = 2;
dictionary.TryGetValue(value.FromServiceId, out value);
//or dictionary.TryGetValue(value.ToServiceId, out value);
if (value != null) MessageBox.Show(value.Id.ToString());

【讨论】:

  • OP 会检查两个不同的属性
  • @S.Akbari ,感谢您的回复,请您描述一下如何使用您的语法。
  • @S.Akbari,感谢您的回复,假设我的 ServiceClass 实例值具有以下信息:ServiceClass value=new ServiceClass();value.FromServiceId=1;value.ToServiceId=2,现在我如何使用你的语法。
  • @S.Akbari,感谢您的宝贵努力,请您告诉我为什么它比我的语法更好。
  • 对于包含输入的实例和 out 变量都使用一个变量 value 不是 TryGetValue 的“规范”或典型示例,因此这可能会让人们失望事先不知道这个方法的人,不必要的困惑。
【解决方案2】:

也许这是一种矫枉过正,但您可以为每个案例创建一个类,该类继承自一个公共接口(我们称之为ICommon),该接口为每个案例公开一个公共方法(在您的案例中为 Create 方法) 然后将该接口注入ServiceClass的构造函数中。

然后,当您想使用ServiceClass 时,您必须提供ICommon(您从每个案例中提取的类之一)的实际实现,最后您只需调用entity.Create

我相信这是策略模式,总而言之,您应该在一个通用接口下的不同类中提取算法。

最后,这种重构将降低代码的分圆复杂度(这主要意味着您减少了代码的分支),这总是一件好事。

【讨论】:

    【解决方案3】:

    您可以做的是将所有变体放入一个枚举中,并完全按照您想要调用的方法调用枚举值。 (我建议不要在名称中使用数字,因为编译器不允许这样做)

    为了简单和可测试性,我将枚举和方法放在同一个类中:

    public class ServiceClass
    {
        public enum ServiceID
        {
            OneKWithdrawal,
            Ten_KWithdrawal,
            BTWithdrawal,
            OneKDeposit,
            Ten_KDeposit,
            BTDeposit
        }
        public ServiceID From_Ser_ID { get; set; }
        public ServiceID To_Ser_ID { get; set; }
    
        public void One_KWithdrawal()
        { Console.WriteLine("One_KWithdrawal"); }
    
        public void Ten_KWithdrawal()
        { Console.WriteLine("Ten_KWithdrawal"); }
    
        public void BTWithdrawal()
        { Console.WriteLine("BTWithdrawal"); }
    
        public void One_KDeposit()
        { Console.WriteLine("One_KDeposit"); }
    
        public void Ten_KDeposit()
        { Console.WriteLine("Ten_KDeposit"); }
    }
    

    这将是执行您的 if 条件方法的方法。它使用反射来访问枚举中编码的方法。您可能必须根据方法所在的位置调整Invoke(sc, null); 调用中的object 参数。如果它们与您调用execute 的位置相同,则可以使用this

    public static void execute(ServiceClass sc)
    {
        sc.GetType().GetMethod(sc.From_Ser_ID.ToString()).Invoke(sc, null);
        sc.GetType().GetMethod(sc.To_Ser_ID.ToString()).Invoke(sc, null);
    }
    

    在这里你可以测试整个代码:

    public static void Main(string[] args)
    {
    
        ServiceClass entity = new ServiceClass();
        entity.From_Ser_ID = ServiceClass.ServiceID.BTWithdrawal;
        entity.To_Ser_ID = ServiceClass.ServiceID.Ten_KDeposit;
    
        execute(entity);
    }
    

    所以你最终会得到一个枚举和两行代码。

    【讨论】:

      【解决方案4】:

      您可以使用如下开关盒:

      var entity = new ServiceClass();
      
      entity.FromServiceID = 3;
      entity.ToServiceID = 1;
      
      switch(entity.FromServiceID)
      {
          case 1:
              new 1KWithdrawal();
              break;
          case 2:
              new 10KWithdrawal();
              break;
          case 3:
              new BTWithdrawal();
              break;
      }
      
      switch(entity.ToServiceID)
      {
          case 1:
              new 1KDeposit();
              break;
          case 2:
              new 10KDeposit();
              break;
          case 3:
              new BTDeposit();
              break;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-27
        • 2023-03-14
        • 1970-01-01
        • 2021-10-13
        • 2018-08-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多