【问题标题】:C# Switch Statement refactoringC# Switch 语句重构
【发布时间】:2009-11-25 15:26:04
【问题描述】:

以下代码的目的是确定特定日期是否符合“周末”条件,即周四下午 12:00 之后、至少 2 天和周一下午 12:00 之前

有没有更好的方法? If-Else 变得丑陋,而 Strategy 模式的工作量太大了。

public bool ValidateWeekend(DateTime pickupDate, DateTime dropoffDate)
    {
        TimeSpan ts = dropoffDate.Subtract(pickupDate);

        if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
        {
            switch (pickupDate.DayOfWeek)
            {
                case DayOfWeek.Thursday:
                    if (pickupDate.Hour >= 12)
                    {
                        switch (dropoffDate.DayOfWeek)
                        {
                            case DayOfWeek.Sunday:
                                return true;
                            case DayOfWeek.Monday:
                                if (dropoffDate.Hour <= 12)
                                {
                                    return true;
                                }
                                return false;
                        }
                    }
                    break;
                case DayOfWeek.Friday:
                    switch (dropoffDate.DayOfWeek)
                    {
                        case DayOfWeek.Sunday:
                            return true;
                        case DayOfWeek.Monday:
                            if (dropoffDate.Hour <= 12)
                            {
                                return true;
                            }
                            return false;
                    }
                    break;
                case DayOfWeek.Saturday:
                    switch (dropoffDate.DayOfWeek)
                    {
                        case DayOfWeek.Sunday:
                            return true;
                        case DayOfWeek.Monday:
                            if (dropoffDate.Hour <= 12)
                            {
                                return true;
                            }
                            return false;
                    }
                    return false;
            }
        }
        return false;
    }

【问题讨论】:

  • 除了将重复的代码重构为下面列出的自己的方法之外,我还非常喜欢使用更实用的解决方案方法。将每一天的逻辑隔离到它自己的特定函数中,然后构建一个以天为键、以适当的方法为值的映射。正如我上面所说,通过将您的取货日期放入他们自己的方法中,然后使用 lamdas 执行您的丢弃逻辑,我认为代码变得更加清晰。

标签: c# refactoring switch-statement


【解决方案1】:

您绝对应该将 dropoffDate 重构出来 - 因为代码重复了 3 次!最简单的清理:我会引入一个函数来检查pickupDate,另一个来检查dropoffDate:

private bool IsPickupWeekend(DateTime pickupDate)
{
    switch (pickupDate.DayOfWeek)
            {
                case DayOfWeek.Thursday:
                    return pickupDate.Hour >= 12;
                case DayOfWeek.Friday:                    
                case DayOfWeek.Saturday:
                    return true;
            }
        }
        return false;
}

private bool IsWeekendDropOff(DateTime dropoffDate)
{
    switch (dropoffDate.DayOfWeek)
                    {
                        case DayOfWeek.Sunday:
                            return true;
                        case DayOfWeek.Monday:
                            if (dropoffDate.Hour <= 12)
                            {
                                return true;
                            }
                            return false;
                    }
                    return false;

}

现在你的主要功能是 2 班轮:

if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
{
    return IsPickupWeekend(pickupDate) && IsWeekendDropOff(dropoffDate);
}

【讨论】:

  • 很确定这将检查上午 12 点而不是下午 12 点
  • @Grzenio:IsWeekendDropOff 函数不应该将星期六作为 Drop Off 的日子吗?考虑到 PickUpDate 是星期四 1300 小时,那么 Drop Date 可以是星期六 1400 小时。
  • 具体见msdn.microsoft.com/en-us/library/system.datetime.hour.aspx“小时分量,表示为0到23之间的值”
  • 问题中提到的下午 12 点是中午 12 点,即 0-23 的时钟是 12 点,所以星期六不应该被视为 DropOff 的一天吗? en.wikipedia.org/wiki/12-hour_clock
  • 我刚刚从问题中复制了一些代码——作者只要求提供一个“不那么难看”的版本——所以我假设问题中的代码“正确”工作。
【解决方案2】:

我想你可以在这里提取一个方法:

private bool ValidateDropoff(DateTime dropoffDate)
{
    switch (dropoffDate.DayOfWeek)
    {
        case DayOfWeek.Sunday:
           return true;
        case DayOfWeek.Monday:
           return dropoffDate.Hour <= 12;
        default:
           return false;
    }
}

【讨论】:

  • 你需要一个'return false;'在末尾;否则,并非每条路径都会返回一个值。或者,只需移动'return false;'你在开关之外。
  • @Gorpik,默认情况下会处理这个问题。实际上,每条路径都会返回一个值。
  • 星期六不应该是这个代码中的一个案例吗?如果 PickUpDate:星期四 1300 Hr 和 Drop Date:星期六 1400 Hr,请告诉我此代码是否有效?
【解决方案3】:
if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
{
    var hour_limit = new Func<Boolean>(() => {
        switch (dropoffDate.DayOfWeek)
        {
            case DayOfWeek.Sunday:
                return true;
            case DayOfWeek.Monday:
                return dropoffDate.Hour <= 12;
            default:
                return false;
        }

    });

    switch (pickupDate.DayOfWeek)
    {
        case DayOfWeek.Thursday:
            if (pickupDate.Hour >= 12)  return hour_limit();
            break;
        case DayOfWeek.Friday:
        case DayOfWeek.Saturday:
            return hour_limit();
        default: 
            break;
    }
}

return false;

【讨论】:

    【解决方案4】:

    不是很清楚,但是你去吧:

    public bool ValidateWeekend(DateTime pickupDate, DateTime dropoffDate){
        TimeSpan ts = dropoffDate.Subtract(pickupDate);
    
        if (ts.TotalDays >= 2 && ts.TotalDays <= 4){
            switch (pickupDate.DayOfWeek){
                case DayOfWeek.Thursday:
                    if (pickupDate.Hour >= 12){
                        switch (dropoffDate.DayOfWeek){
                            case DayOfWeek.Sunday:
                                return true;
                            case DayOfWeek.Monday:
                                return dropoffDate.Hour <= 12;
                        }
                    }
                    break;
                case DayOfWeek.Friday:
                    switch (dropoffDate.DayOfWeek){
                        case DayOfWeek.Sunday:
                            return true;
                        case DayOfWeek.Monday:
                            return dropoffDate.Hour <= 12;
                    }
                    break;
                case DayOfWeek.Saturday:
                    switch (dropoffDate.DayOfWeek){
                        case DayOfWeek.Sunday:
                            return true;
                        case DayOfWeek.Monday:
                            return dropoffDate.Hour <= 12;
                    }
                    return false;
            }
        }
        return false;
    }
    

    【讨论】:

      【解决方案5】:

      我的第一次破解:

      if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
              {
                  switch (pickupDate.DayOfWeek)
                  {
                      case DayOfWeek.Thursday:
                      case DayOfWeek.Friday:
                      case DayOfWeek.Saturday:
                          if (pickupDate.DayOfWeek == DayOfWeek.Thursday && pickupDate.Hour <= 12)
                              return false;
      
                          switch (dropoffDate.DayOfWeek)
                          {
                              case DayOfWeek.Sunday:
                                  return true;
                              case DayOfWeek.Monday:
                                  return dropoffDate.Hour <= 12;
                          }
                          return false;
      
                      default:
                          return false;
                  }
              }
              return false;
      

      【讨论】:

        【解决方案6】:

        在switch中尝试

        retrun (dropoffDate.DayOfWeek == DayOfWeek.Sunday && dropoffDate.Hour <= 12 || dropoffDate.DayOfWeek == DayOfWeek.Sunday)
        

        【讨论】:

          【解决方案7】:

          我会这样做

          public bool ValidateWeekend(DateTime pickupDate, DateTime dropoffDate)
          {
              TimeSpan ts = dropoffDate.Subtract(pickupDate);
          
              if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
              {
                  switch (pickupDate.DayOfWeek)
                  {
                      case DayOfWeek.Thursday:
                          if (pickupDate.Hour >= 12)
                          {
                              reurn DayOfWeek(dropOffDate.DayOfWeek);
                          }
                          break;
                      case DayOfWeek.Friday, DayOfWeek.Saturday:
                          {
                              return DayOfWeek(dropOffDate.DayOfWeek);
                          }
                  }
              }
              return false;
          }
          
          public bool DayOfWeek(DateTime dropOffDate)
              {
          switch (dropoffDate.DayOfWeek)
              {
                  case DayOfWeek.Sunday:
                      {
                          return true;
                      }
                  case DayOfWeek.Monday:
                      {
                          if (dropoffDate.Hour <= 12)
                              {
                                  return true;
                              }
                          return false;
                      }
                 return false;
             }
           }
          

          【讨论】:

            【解决方案8】:

            这是我的尝试:

              /// <summary>
                /// Gets the weekend days.
                /// </summary>
                /// <returns></returns>
                public List<DayOfWeek> GetWeekendDays()
                {
                    List<DayOfWeek> days = new List<DayOfWeek>()
                                               {
                                                   DayOfWeek.Thursday,
                                                   DayOfWeek.Friday,
                                                   DayOfWeek.Sunday
                                               };
                    return days;
                }
            
                /// <summary>
                /// Validates the weekend.
                /// </summary>
                /// <param name="pickupDate">The pickup date.</param>
                /// <param name="dropoffDate">The dropoff date.</param>
                /// <returns></returns>
                public bool ValidateWeekend(DateTime pickupDate, DateTime dropoffDate)
                {
                    bool isValid = false;
                    TimeSpan ts = dropoffDate.Subtract(pickupDate);
            
                    if (ts.TotalDays >= 2 && ts.TotalDays <= 4)
                    {
                        List<DayOfWeek> days = GetWeekendDays();
            
                        foreach (DayOfWeek day in days)
                        {
                            if(pickupDate.DayOfWeek == day)
                            {
                               isValid = ValidateDropOff(dropoffDate);
                                break;
                            }
                        }
                    }
            
                    return isValid;
                }
            
                /// <summary>
                /// Validates the drop off.
                /// </summary>
                /// <param name="dropoffDate">The dropoff date.</param>
                /// <returns></returns>
                private static bool ValidateDropOff(DateTime dropoffDate)
                {
                    bool isValidDropOff = (dropoffDate.DayOfWeek == DayOfWeek.Sunday);
            
                    if(dropoffDate.DayOfWeek == DayOfWeek.Monday)
                    {
                        if (dropoffDate.Hour <= 12)
                        {
                            isValidDropOff = true;
                        }
                    }
            
                    return isValidDropOff;
                }
            

            【讨论】:

              【解决方案9】:
                  private readonly TimeSpan Midday = new TimeSpan(12, 0, 0);
              
                  public bool ValidateWeekend(DateTime pickupDate, DateTime dropoffDate)
                  {
                      TimeSpan lengthOfTrip = dropoffDate.Subtract(pickupDate);
              
                      if (lengthOfTrip.TotalDays < 2 || lengthOfTrip.TotalDays > 4)
                          return false;
              
                      return IsPickupDateConsideredWeekend(pickupDate) && IsDropoffDateConsideredWeekend(dropoffDate);
                  }
              
                  private bool IsPickupDateConsideredWeekend(DateTime pickupdate)
                  {
                      if (pickupdate.DayOfWeek == DayOfWeek.Thursday && pickupdate.TimeOfDay > Midday)
                          return true;
                      return false;
                  }
              
                  private bool IsDropoffDateConsideredWeekend(DateTime dropoffDate)
                  {
                      if (dropoffDate.DayOfWeek == DayOfWeek.Monday && dropoffDate.TimeOfDay <= Midday)
                          return true;
                      return false;
                  }
              

              【讨论】:

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