【问题标题】:Should this (Generic Range Class) Conditional logic be replaced with Polymorphism? If yes, then why?这个(通用范围类)条件逻辑应该用多态性代替吗?如果是,那为什么?
【发布时间】:2012-04-27 20:26:55
【问题描述】:

下面显示的是一个通用范围类。这样做的目的是保存一个范围,然后在请求时指定(布尔值)给定值是否在范围内。

我已经阅读了多个帖子、问题、博客等,上面写着“Replace Conditional with Polymorphism

我的问题是,是否真的值得将代码分成多个类,每个类实际上只有一行代码。希望下面的代码能说明我的意思。

该类依赖于另外两个类,此处未显示,但如果有人需要,我可以稍后包含它。

namespace Common.Utilities
{
    public class GenericRange<T>
       where T : struct, IComparable<T>
   {
      #region Properties
      public T Min { get; private set; }
      public T Max { get; private set; }
      public GenericRangeType RangeType { get; private set; }
      #endregion

      #region Constructors
      public GenericRange(T min, T max, GenericRangeType rangeType = GenericRangeType.Inclusive)
      {
         // Check Parameters
         Min = min;
         Max = max;
         RangeType = rangeType;
      }
      #endregion

      #region Methods
      #region Private
      private bool IsInclusive(T value)
      {
         return value.IsGreaterThanOrEqualTo(Min) && value.IsLessThanOrEqualTo(Max);
      }

      private bool IsInclusiveMin(T value)
      {
         return value.IsGreaterThanOrEqualTo(Min) && value.IsLessThan(Max);
      }

      private bool IsInclusiveMax(T value)
      {
         return value.IsGreaterThan(Min) && value.IsLessThanOrEqualTo(Max);
      }

      private bool IsExclusive(T value)
      {
         return value.IsGreaterThan(Min) && value.IsLessThan(Max);
      }
      #endregion

      #region Public
      public bool Contains(T value)
      {
         switch (RangeType)
         {
            case GenericRangeType.Inclusive: return IsInclusive(value);
            case GenericRangeType.InclusiveMin: return IsInclusiveMin(value);
            case GenericRangeType.InclusiveMax: return IsInclusiveMax(value);
            case GenericRangeType.Exclusive: return IsExclusive(value);
            default: throw new NotImplementedException();
         }
      }

      public override string ToString()
      {
         return String.Format("Min: {0}, Max: {1}, Type: {2}", Min, Max, RangeType);
      }
      #endregion
      #endregion
    }
}

唯一的公共方法是:Contain 和 ToString。 如果我通过多态正确理解它,我应该为每个比较类型创建一个单独的具体类,然后使 Contain 成为一个虚拟方法。

我想了解的主要问题是,好处/优势是什么?

如果这是这个问题的错误地方,那么我很抱歉。告诉我,我会搬家的。

编辑 1: 如果有人需要,可以完成此操作的附加代码:

public static class ComparableExtensions
{
    public static bool IsEqualTo<T>(this T leftHand, T value) where T : IComparable<T>
    {
        return leftHand.CompareTo(value) == 0;
   }

    public static bool IsGreaterThan<T>(this T leftHand, T value) where T : IComparable<T>
    {
        return leftHand.CompareTo(value) > 0;
    }
    public static bool IsGreaterThanOrEqualTo<T>(this T leftHand, T value) where T : IComparable<T>
    {
        return leftHand.CompareTo(value) >= 0;
    }

    public static bool IsLessThan<T>(this T leftHand, T value) where T : IComparable<T>
    {
        return leftHand.CompareTo(value) < 0;
    }
    public static bool IsLessThanOrEqualTo<T>(this T leftHand, T value) where T : IComparable<T>
    {
        return leftHand.CompareTo(value) <= 0;
    }
}   

public enum GenericRangeType
{
    Inclusive,
    Exclusive,
    InclusiveMin,
    InclusiveMax
}

【问题讨论】:

    标签: c# oop generics if-statement switch-statement


    【解决方案1】:

    将其拆分为不同的类可让您在不更改现有代码的情况下扩展 Contains。在这种情况下,它没有太大意义,因为您已经涵盖了 contains 的所有基础,但在其他情况下,可扩展性可能非常有用。

    【讨论】:

      【解决方案2】:

      IMO - 您使用的泛型更像是“模板”类,而不是经典 OOPS 术语中的纯粹基类。

      我的意思是,如果你写了这样的类:

      public class GenericRange{...}
      
      public class IntRange : GenericRange{...}
      public class DecimalRange : GenericRange{...}
      

      在这种情况下,真正将 Contains 的实现分解为单独的子类型作为重写方法是有意义的。

      但由于您使用的是代码模板,因此您确实会获得多态行为的好处,这取决于您初始化模板类的方式。

      所以,如果你这样做了:

      new GenericRange<int>(1, 100, inclusive);
      new GenericRange<decimal>(1.0, 100.0, inclusive);
      

      您已经完成了多态行为,我认为这是泛型的一大好处,因为它允许您对此类代码进行模板化,而不是像前面所示的那样拥有专门的子类。

      【讨论】:

        【解决方案3】:

        我认为你所拥有的很好,只要它在未来不需要扩展太多,并且你不需要它成为可以在其他程序集中扩展的公共类。如果您想要更多的灵活性,您可以使用多态性,或者创建一个Func&lt;T, bool&gt;(可能是private,因为您可能只想公开Contains 方法,而不是它使用a 实现的事实Func) 在设置RangeType 时设置。那么你的Contains 方法就变成了return myFunc(value);

        【讨论】:

        • 我不太懂 Func、Anonymous、Expressions、Delegates。这或多或少是在声明一个代表。我首先声明了一个代表,但后来并没有看到太多优势。你能否给我一个更好的解释,在 Func 上做一个小样本会让这更好
        猜你喜欢
        • 1970-01-01
        • 2020-08-01
        • 2021-05-11
        • 1970-01-01
        • 2010-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多