skip to Main Content

Looking for a way to find is object between two objects. Tried to convert integer to decimal using

static bool Between(object value, object low, object high)
  {
    if (value == null && low == null && high == null)
      return false;

    if (value is int || low is int || high is int ||
      value is decimal || low is decimal || high is decimal ||
      value is double || low is double || high is double ||
      value is int? || low is int? || high is int? ||
      value is decimal? || low is decimal? || high is decimal? ||
      value is double? || low is double? || high is double? )
     return (decimal)(value ?? 0) >= (decimal)(low ?? 0) && (decimal)(value ?? 0) <= (decimal)(high ?? 0);

    if (value is DateOnly || low is DateOnly || high is DateOnly ||
      value is DateOnly? || low is DateOnly? || high is DateOnly?)
      return (DateOnly)(value ?? DateOnly.MinValue) >= (DateOnly)(low ?? DateOnly.MinValue) && (DateOnly)(value ?? 0) <= (DateOnly)(high ?? DateOnly.MinValue);

    if (value is string || low is string || high is string ||
      value is char || low is char || high is char
      value is string || low is string || high is string ||
      value is char? || low is char? || high is char? )
    {
      string av = (string)(value ?? "");
      string slow = (string)(low ?? "");
      string shigh = (string)(high ?? "");
      return av.CompareTo(slow) >= 0 && av.CompareTo(shigh) <= 0;
    }
    throw new ArgumentException("Incompatible argument types");
  }

Using mixed int and decimal arguments

 Between((int)1 , (decimal)1, (decimal) 2 )

throws exception

Cannot cast integer to decimal

How fix this methid it so it works if arguments are int, decimal, double, int?, decimal? or double? in any combinations.
Can using dynamic arument tupes insted of object type make it easier?

Using ASP .NET 8 MVC with latest C#

2

Answers


  1. As a quick solution, you can use decimal.TryParse() and ToString().

        object input1 = (int)1;
        object input2 = (int)2;
        decimal.TryParse(input1.ToString(), out decimal parse);
        bool compareBool1 = (decimal)parse <= (decimal)input2; // This works.
        bool compareBool2 = (decimal)input1 <= (decimal)input2; // InvalidCastException
    

    However, there are still many issues.

    Login or Signup to reply.
  2. How about this approach?

    static class Utility
    {
        static bool IsNumericType(object value) =>
            value is int || value is decimal || value is double ||
            value is int? || value is decimal? || value is double?;
    
        static bool IsDateOnlyType(object value) =>
            value is DateOnly || value is DateOnly?;
    
        static bool IsStringOrCharType(object value) =>
            value is string || value is char || value is char?;
    
        static decimal ToDecimal(object value) =>
            decimal.TryParse(value.ToString(), out var result) ? result : 0;
    
        static DateOnly ToDateOnly(object value) => (DateOnly)(value ?? DateOnly.MinValue);
            static string ToStringValue(object value) => (string)(value ?? "");
    
        static bool CompareNumeric(object value, object low, object high) =>
            ToDecimal(value) >= ToDecimal(low) && ToDecimal(value) <= ToDecimal(high);
    
        static bool CompareDateOnly(object value, object low, object high) =>
            ToDateOnly(value) >= ToDateOnly(low) && ToDateOnly(value) <= ToDateOnly(high);
    
        static bool CompareStringOrChar(object value, object low, object high) =>
            ToStringValue(value).CompareTo(ToStringValue(low)) >= 0 &&
            ToStringValue(value).CompareTo(ToStringValue(high)) <= 0;
    
        public static bool Between(object value, object low, object high)
        {
            if (value == null && low == null && high == null)
                return false;
    
            if (IsNumericType(value) || IsNumericType(low) || IsNumericType(high))
                return CompareNumeric(value, low, high);
    
            if (IsDateOnlyType(value) || IsDateOnlyType(low) || IsDateOnlyType(high))
                return CompareDateOnly(value, low, high);
    
            if (IsStringOrCharType(value) || IsStringOrCharType(low) || IsStringOrCharType(high))
                return CompareStringOrChar(value, low, high);
    
            throw new ArgumentException("Incompatible argument types");
        }
    }
    

    Or the following approach that preserves object-oriented encapsulation?

    public class Value
    {
        public object Data { get; private set; }
    
        public Value(object data)
        {
            Data = data;
        }
    
        public bool IsNumeric() =>
            Data is int || Data is decimal || Data is double ||
            Data is int? || Data is decimal? || Data is double?;
    
        public bool IsDateOnly() =>
            Data is DateOnly || Data is DateOnly?;
    
        public bool IsStringOrChar() =>
            Data is string || Data is char || Data is char?;
    
        public decimal ToDecimal() =>
            decimal.TryParse(Data.ToString(), out var result) ? result : 0;
    
        public DateOnly ToDateOnly() =>
            Data is DateOnly date ? date : DateOnly.MinValue;
    
        public string ToStringValue() =>
            Data?.ToString() ?? string.Empty;
    }
    
    public static class Utility
    {
        public static bool Between(Value value, Value low, Value high)
        {
            if (value == null && low == null && high == null)
                return false;
    
            if (value.IsNumeric() || low.IsNumeric() || high.IsNumeric())
                return value.ToDecimal() >= low.ToDecimal() && value.ToDecimal() <= high.ToDecimal();
    
            if (value.IsDateOnly() || low.IsDateOnly() || high.IsDateOnly())
                return value.ToDateOnly() >= low.ToDateOnly() && value.ToDateOnly() <= high.ToDateOnly();
    
            if (value.IsStringOrChar() || low.IsStringOrChar() || high.IsStringOrChar())
                return value.ToStringValue().CompareTo(low.ToStringValue()) >= 0 &&
                       value.ToStringValue().CompareTo(high.ToStringValue()) <= 0;
    
            throw new ArgumentException("Incompatible argument types");
        }
    }
    
    // Usage
    Value intValue = new Value((int)5);
    Value lowInt = new Value((decimal)1);
    Value highInt = new Value((decimal)10);
    bool isInRangeInt = Utility.Between(intValue, lowInt, highInt);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search