重构If else树

时间:2009-09-03 17:12:12

标签: c# .net refactoring

我有一个if else树会随着我添加额外的项目来维持而且我正在寻找最好的方法来编写它以保持可维护性我从这个代码开始

private void ControlSelect()
{

    if (PostingType == PostingTypes.Loads && !IsMultiPost)
    {
        singleLoadControl.Visible = true;
          singleTruckControl.Visible = false;
          multiTruckControl.Visible = false;
          multiLoadControl.Visible = false;
    }
    else if (PostingType == PostingTypes.Trucks && !IsMultiPost)
    {
        singleLoadControl.Visible = false;
          singleTruckControl.Visible = true;
          multiTruckControl.Visible = false;
          multiLoadControl.Visible = false;
    }
    else if (PostingType == PostingTypes.Loads && IsMultiPost)
    {
        singleLoadControl.Visible = false;
          singleTruckControl.Visible = false;
          multiTruckControl.Visible = false;
          multiLoadControl.Visible = true;
    }
    else if (PostingType == PostingTypes.Trucks && IsMultiPost)
    {
        singleLoadControl.Visible = false;
        singleTruckControl.Visible = false;
          multiTruckControl.Visible = true;
        multiLoadControl.Visible = false;
    }
}

并考虑将其重新分解为类似的东西

private void ControlSelect()
{
    List<UserControl> controlList = GetControlList();

      string visableControl = singleLoadControl.ID;
      if (PostingType == PostingTypes.Loads && !IsMultiPost)
      {
        visableControl = singleLoadControl.ID;
      }
      else if (PostingType == PostingTypes.Trucks && !IsMultiPost)
      {
        visableControl = singleTruckControl.ID;
      }
      else if (PostingType == PostingTypes.Loads && IsMultiPost)
      {
        visableControl = multiLoadControl.ID;
      }
      else if (PostingType == PostingTypes.Trucks && IsMultiPost)
      {
        visableControl = multiTruckControl.ID;
      }

      foreach (UserControl userControl in controlList)
      {
        userControl.Visible = (userControl.ID == visableControl);
      }
}

private List<UserControl> GetControlList()
{
    List<UserControl> controlList = new List<UserControl>
      {
        singleLoadControl,
            multiTruckControl,
            singleTruckControl,
            multiLoadControl
      };
      return controlList;
}

我的表现很受欢迎,但我可以管理我的所有控件都是一个地方

我的另一个想法是让每个选定的控制块都有自己的方法,就像这样

private void SetSingleLoadControlAsSelected()
{
      singleLoadControl.Visible = true;
      singleTruckControl.Visible = false;
      multiTruckControl.Visible = false;
      multiLoadControl.Visible = false;
}

我没有受到性能影响,但我在多个位置维护控件

我只是因为我喜欢它的可维护性而倾向于选择一个。

8 个答案:

答案 0 :(得分:23)

怎么样

singleLoadControl.Visible  = 
      PostingType == PostingTypes.Loads  && !IsMultiPost;      
singleTruckControl.Visible = 
      PostingType == PostingTypes.Trucks && !IsMultiPost;      
multiTruckControl.Visible  = 
      PostingType == PostingTypes.Loads  && IsMultiPost;      
multiLoadControl.Visible   =  
      PostingType == PostingTypes.Trucks && IsMultiPost;

如果您希望能够使多个控件可见(或添加更多枚举值),请使用[Flags]属性修饰枚举,如下所示:

[Flags]   
public enum PostTyp { None=0, IsMultiPost = 1, Loads = 2, Trucks = 4 }

并修改代码如下:

singleLoadControl.Visible  = 
      ((PostingType &  (PostTyp.Loads | ~PostTyp.MultiCast)) 
         == PostingType );      
singleTruckControl.Visible = 
      ((PostingType & (PostTyp.Trucks | ~PostTyp.MultiCast)) 
         == PostingType );          
multiTruckControl.Visible  = 
      ((PostingType & (PostTyp.Loads  |  PostTyp.MultiCast)) 
         == PostingType );        
multiLoadControl.Visible   =  
      ((PostingType & (PostTyp.Trucks |  PostTyp.MultiCast)) 
         == PostingType );      

答案 1 :(得分:6)

当您似乎使用枚举时,我建议使用默认情况下的开关来处理未知值。我相信这种方法使得意图比完成任务中的所有检查更清晰。

switch (PostingType)
{
case PostingTypes.Loads:
   singleLoadControl.Visible = !IsMultiPost;
   multiTruckControl.Visible = IsMultiPost;
   singleTruckControl.Visible = false;
   multiTruckLoadControl.Visible = false;
   break;

case PostingTypes.Trucks:
   singleLoadControl.Visible = false;
   multiTruckControl.Visible = false;
   singleTruckControl.Visible = !IsMultiPost;
   multiLoadControl.Visible = IsMultiPost;
   break;

default:
   throw InvalidOperationException("Unknown enumeration value.");
}

答案 2 :(得分:5)

这个怎么样:

     singleLoadControl.Visible = false;
     singleTruckControl.Visible = false;
     multiTruckControl.Visible = false;
     multiLoadControl.Visible = false;

    if (PostingType == PostingTypes.Loads && !IsMultiPost)
    {
            singleLoadControl.Visible = true;
    }
    else if (PostingType == PostingTypes.Trucks && !IsMultiPost)
    {
          singleTruckControl.Visible = true;
    }
    else if (PostingType == PostingTypes.Loads && IsMultiPost)
    {
        multiLoadControl.Visible = true;
    }
    else if (PostingType == PostingTypes.Trucks && IsMultiPost)
    {
          multiTruckControl.Visible = true;
}

答案 3 :(得分:2)

如果它是合情合理的(例如,如果这些已经是特定于域的自定义控件),您可以将逻辑封装在控件本身(Replace Conditional with Polymorphism)中。也许创建一个这样的界面:

public interface IPostingControl {
    void SetVisibility(PostingType postingType, bool isMultiPost);
}

然后每个控件都要负责自己的可见性规则:

public class SingleLoadControl: UserControl, IPostingControl {

    // ... rest of the implementation
    public void SetVisibility(PostingType postingType, bool isMultiPost) {
        this.Visible = postingType == PostingType.Load && !isMultiPost);
    }
}

最后,在您的网页中,只需迭代IPostingControls并致电SetVisibility(postingType, isMultiPost)

答案 4 :(得分:1)

如果您希望添加许多不同的参数,可以创建一个多维的对象数组

Arr[0][0] = singleLoadControl
Arr[0][1] = singleTruckControl
Arr[1][0] = multiLoadControl
Arr[1][1] = multiTruckControl

这非常可怕,但是if语句更简单。如果您无论如何都要对控件进行大量引用,我宁愿使用基于代码的表示来表示这些负载是什么。这样的数组可以包装在一个类中,以便您使用类似以下内容访问元素:

ControlClassInstance.single.truck

您的代码如下:

p1 = IsMultiPost ? ControlClassInstance.multi : ControlClassInstance.single
p2 = p1[PostingType] //(this call would mean adding an indexer)

这种解决方案太复杂了,除非你期望事情变得复杂......而且可能也很差。

答案 5 :(得分:1)

  singleLoadControl.Visible = false;
  singleTruckControl.Visible = false;
  multiTruckControl.Visible = false;
  multiLoadControl.Visible = false;


  singleLoadControl.Visible = (PostingType == PostingTypes.Loads && !IsMultiPost);
  singleTruckControl.Visible = (PostingType == PostingTypes.Trucks && !IsMultiPost);
  multiLoadControl.Visible = (PostingType == PostingTypes.Loads && IsMultiPost);
  multiTruckControl.Visible = (PostingType == PostingTypes.Trucks && IsMultiPost);

答案 6 :(得分:1)

您是否考虑过State Pattern

答案 7 :(得分:-1)

private void ControlSelect()
{
    if (PostingType == PostingTypes.Loads && !IsMultiPost)
    {
        singleLoadControl.Visible = true;
        singleTruckControl.Visible = false;
        multiTruckControl.Visible = false;
        multiLoadControl.Visible = false;
        return;
    }
    if (PostingType == PostingTypes.Trucks && !IsMultiPost)
    {
        singleLoadControl.Visible = false;
        singleTruckControl.Visible = true;
        multiTruckControl.Visible = false;
        multiLoadControl.Visible = false;
        return;
    }
    if (PostingType == PostingTypes.Loads && IsMultiPost)
    {
        singleLoadControl.Visible = false;
        singleTruckControl.Visible = false;
        multiTruckControl.Visible = false;
        multiLoadControl.Visible = true;
        return;
    }
    if (PostingType == PostingTypes.Trucks && IsMultiPost)
    {
        singleLoadControl.Visible = false;
        singleTruckControl.Visible = false;
        multiTruckControl.Visible = true;
        multiLoadControl.Visible = false;
        return;
    }
}