I have a need to restrict certain numbers to valid ranges in my application. I created delegates to handle this. I don't know if this is the right way to do it; I'm running into something that feels wrong.
public delegate int RestrictInteger(int minimum, int maximum, int value);
public delegate decimal RestrictDecimal(decimal minumum, decimal maximum, decimal value);
class GameMath
{
public static int RestrictNumber(int minimum, int maximum, int value)
{
if (value < minimum) { value = minimum; }
else if (value > maximum) { value = maximum; }
return value;
}
public static decimal RestrictNumber(decimal minimum, decimal maximum, decimal value)
{
if (value < minimum) { value = minimum; }
else if (value > maximum) { value = maximum; }
return value;
}
}
public class SomeClass
{
public int aValue { get; set; }
public void SetValue(int value)
{
RestrictInteger doRestrict = new RestrictInteger(GameMath.RestrictNumber);
this.aValue = doRestrict(0, 100, value);
}
}
On one hand, it seems like if I added more signatures, then I'd want to be able to do different things with them (say, conversions, or rounding, etc.). On the other hand, between these two signatures, the code is precisely the same. Is that okay, or is there some way to write one operation which applies to both these cases, even if other cases might use different operations?
Yes, you can do this with generics - although not with <
and >
. You should use the fact that these types implement IComparable<T>
for themselves:
public static T RestrictNumber<T>(T min, T max, T value) where T : IComparable<T>
{
return value.CompareTo(min) < 0 ? min
: value.CompareTo(max) > 0 ? max
: value;
}
(You could still use your original code here - I rather like this sort of use of the conditional operator though; it satisfies my growing functional tendencies.)