예제 #1
0
        /// <summary>
        /// Throw an exception if value is not within range or an increment multiple.
        /// </summary>
        /// <param name="range"></param>
        /// <param name="value"></param>
        /// <param name="paramName"></param>
        public static void Validate(this InclusiveRange range, decimal value, string paramName = null)
        {
            Throw.IfNull(range, nameof(range));

            if (value < range.Minimum)
            {
                throw new ArgumentOutOfRangeException(paramName ?? nameof(value), $"Value ({value}) must be greater than or equal to minimum ({range.Minimum}).");
            }

            if (value > range.Maximum)
            {
                throw new ArgumentOutOfRangeException(paramName ?? nameof(value), $"Value ({value}) must be less than or equal to maximum ({range.Maximum}).");
            }

            if ((value - range.Minimum) % range.Increment > 0)
            {
                throw new ArgumentOutOfRangeException(paramName ?? nameof(value), $"Value ({value}) must be a multiple of the increment ({range.Increment}).");
            }
        }
예제 #2
0
        /// <summary>
        /// Get the nearest valid value within range coercing remainders to the closest increment.
        /// Specify a midpoint rounding behavior for values with remainder equals increment / 2.
        /// The default behavior rounds midpoint remainders to the nearest even increment.
        ///
        /// For example:
        ///   1.234 => 1.230 given range of [0.01 - 10.00] with increment of 0.01.
        ///   2.345 => 2.340 given range of [0.01 - 10.00] with increment of 0.01 (midpoint rounding to even).
        ///   2.345 => 2.350 given range of [0.01 - 10.00] with increment of 0.01 (midpoint rounding away from 0).
        ///   9.876 => 9.880 given range of [0.01 - 10.00] with increment of 0.01.
        /// </summary>
        /// <param name="range"></param>
        /// <param name="value"></param>
        /// <param name="midpointRounding"></param>
        /// <returns></returns>
        public static decimal GetValidValue(this InclusiveRange range, decimal value, MidpointRounding midpointRounding = MidpointRounding.ToEven)
        {
            if (value <= range.Minimum)
            {
                return(range.Minimum);
            }
            if (value >= range.Maximum)
            {
                return(range.Maximum);
            }

            var remainder = value % range.Increment;

            if (remainder == 0)
            {
                return(value);
            }

            var midpoint = range.Increment / 2;
            var lower    = value - remainder;

            if (remainder < midpoint)
            {
                return(lower);
            }
            if (remainder > midpoint)
            {
                return(lower + range.Increment);
            }

            // Otherwise, remainder equals increment / 2...

            if (midpointRounding == MidpointRounding.AwayFromZero)
            {
                return(lower + range.Increment);
            }

            // Round to nearest even increment...
            return(lower % (range.Increment * 2) == 0
                ? lower // ...if lower is even.
                : lower + range.Increment);
        }
예제 #3
0
        /// <summary>
        /// Get the nearest valid value within range coercing remainders UP to the next increment.
        ///
        /// For example, use this to get a valid quantity given an expected minimum amount:
        ///   1.234 => 1.240 given range of [0.01 - 10.00] with increment of 0.01.
        /// </summary>
        /// <param name="range"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static decimal GetUpperValidValue(this InclusiveRange range, decimal value)
        {
            if (value <= range.Minimum)
            {
                return(range.Minimum);
            }
            if (value >= range.Maximum)
            {
                return(range.Maximum);
            }

            var remainder = value % range.Increment;

            if (remainder == 0)
            {
                return(value);
            }

            return(value - value % range.Increment + range.Increment);
        }
예제 #4
0
        /// <summary>
        /// Verify a value is within range and a multiple of the increment.
        /// </summary>
        /// <param name="range"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsValid(this InclusiveRange range, decimal value)
        {
            Throw.IfNull(range, nameof(range));

            return(value >= range.Minimum && value <= range.Maximum && (value - range.Minimum) % range.Increment == 0);
        }