Home:ALL Converter>Should this (Generic Range Class) Conditional logic be replaced with Polymorphism? If yes, then why?

Should this (Generic Range Class) Conditional logic be replaced with Polymorphism? If yes, then why?

Ask Time:2012-04-28T04:26:55         Author:Pranav Shah

Json Formatter

Shown below is a Generic Range class. The purpose of this is to save a Range and then later when requested specify (boolean) if a given value is in the range.

I have read multiple posts, questions, blogs etc. that say "Replace Conditional with Polymorphism"

My question, is it really worth separating the code out into multiple classes where each class would literally have one line of code. Hopefully the code below will show what I mean.

The class is dependent on two more classes, which are not shown here, but if anyone needs it I can include it later.

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
    }
}

The only Public methods are: Contain and ToString. If I understand it correctly through Polymorphism I should create a separate concrete class for each of the comparisson types and then make Contain a virtual method.

The main thing I am trying to understand is, what would the benefits/advantages be?

If this is the wrong place for this question, then I am sorry. Let me know and I will move it.

EDIT 1: The additional code to make this complete if anyone needs it:

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
}

Author:Pranav Shah,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/10357393/should-this-generic-range-class-conditional-logic-be-replaced-with-polymorphis
Jeff Cuscutis :

Breaking it out to different classes lets you extend Contains without changing the existing code. In this case it doesn't make too much sense as you have covered all the bases of contains here, but in other cases that extensibility can be very useful.",
2012-04-27T20:36:52
Sunny :

IMO - you have used generics which is more of a \"Template\" class rather than purely a base class in the classic OOPS terminology. \n\nWhat I mean to say is, if you had written classes like:\n\npublic class GenericRange{...}\n\npublic class IntRange : GenericRange{...}\npublic class DecimalRange : GenericRange{...}\n\n\nIn this case, it would make sense to really break out the implementation of Contains into the separate sub-types as overridden methods.\n\nBut since you are using a code template, you do get the benefits of polymorphic behavior which is dependant on the way you initialize the template class.\n\nSo, if you did:\n\nnew GenericRange<int>(1, 100, inclusive);\nnew GenericRange<decimal>(1.0, 100.0, inclusive);\n\n\nyou do already have the polymorphic behavior done, I see this as a great benefit of Generics as it allows you to template such code rather than have specialized sub-classes as shown previously.",
2012-04-27T20:43:34
yy