If you've ever needed to limit a value between two known limits of values, then you have been looking for Clamping.
Sometimes when you do calculations on values you know that the result should not fall outside two specific values. For example, if your calculating a percentage-value as an int
-value, then you know the result should be between 0
and 100
.
public int GetPercentage(int val1, int val2)
{
var calculation = val1 / val2;
var ensuredPercentage = calculation.Clamp(0, 100);
return ensuredPercentage;
}
This functionality can easily be extended to all classes which inherits from System.IComparable<T>
, which are for example all types of numbers like int
, double
, long
and so on, but also DateTime
and more.
The following extension-method adds the Clamp
-method to all objects of types inheriting from IComparable<T>
:
public static T Clamp<T>(this T value, T min, T max)
where T : IComparable<T>
{
var comparer = Comparer<T>.Default;
if (comparer == null)
throw new ArgumentException($"Failed to get default comparer for type '{typeof(T).FullName}'.");
var isMinGreaterThanMax = comparer.Compare(min, max) > 0;
if (isMinGreaterThanMax)
{
throw new ArgumentOutOfRangeException(
nameof(min),
"Minimum value cannot be larger than maximum value.");
}
var isValueLessThanMin = comparer.Compare(value, min) < 0;
var isValueGreaterThanMax = !isValueLessThanMin && comparer.Compare(value, max) > 0;
return isValueLessThanMin ? min : (isValueGreaterThanMax ? max : value);
}