Why does the compiler not accept this generic function?
public static T clipGN<T>(this T v, T lo, T hi) where T : decimal,double
{ return Math.Max(lo, Math.Min(hi, v)); }
gives for the second line:
Argument 1: cannot convert from 'T' to 'decimal'
Why? I thought both types meeting that T constraint can be converted to decimal.
BTW, an acceptable alternative coding can be found in the answer here: How should one best recode this example extension method to be generic for all numeri开发者_StackOverflow中文版c types?
I tried compiling that code myself and I receive the following error myself:
'double' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter. (CS0701)
Same for decimal
. This suggests that neither decimal
nor double
are allowed to constrain the type parameter T since the only types that could meet that constraint are themselves (it would be no different from making a non-generic overload, replacing T with either decimal
or double
). Even if, individually, they were allowed to constrain T (which they are not), the combination constraint should still not be allowed since no type can simultaneously be a decimal
and a double
.
This is unlike if the constraint had read where T : IComparable<T>
, where both types, as well as other types, can meet that constraint.
You don't need generics for this. While the concept of "DRY" makes the idea of coding a single function that can work for all types, this is a case where you're better off having discreet functions for each numeric type. All of the numeric types are known, and the list is not overly large; there are likely numeric types that you aren't actually going to use, anyway. If you really (for whatever reason) want a single function, then your only real option is the IComparable
option that you linked to, which has the unfortunate (and unnecessary) consequence of causing boxing on the numeric parameters.
That being said, your problem is that you cannot have T : decimal, double
, as that means that T
must be both decimal
and double
(which is impossible), not that it can be either one.
In addition, since this is all that this function does, I'd probably not call the Math.Max
and Math.Min
functions anyway. It's probably just as simple, if not slightly clearer, to write the functions this way:
public static decimal ClipGN(this decimal v, decimal lo, decimal hi)
{
return v <= lo ? lo : v >= hi ? hi : v;
}
And you should be able to duplicate this code verbatim (apart from the return and parameter types, of course) for each of the numeric types.
精彩评论