I'm trying to write an extension method on numeric types to be used in a fluent testing framework I'm building. Basically, I want to do this:
public static ShouldBeGreaterThan<T>(this T actual, T expected, string message)
where T : int || T: double || etc...
Just where T : struct
doesn't do, since that will also match string
and bool
, and possibly something else I'm forgetting. is there something I can do to match only numeric types? (Specifically types that implement the >
and <
operators, so I can compare them... If this means I'm matching dates as well, it doesn't really matter - the extension will still do what I expect.)
In this case you want to constrain your generic to
IComparable
interface, which gives you access to theCompareTo
method, since this interface allows you to answer the questionShouldBeGreaterThan
.Numeric types will implement that interface and the fact that it also works on strings shouldn't bother you that much.
This workaround may help: Workaround using policies. It provides compile time safety.
You can add the struct constraint if you want as well.
That's the closest I can get to a numeric constraint. All the numeric types implement these 5 interfaces, but IFormattable is not implemented by bool, and strings are a reference type, so they're not applicable.
There's some other things that implement these - DateTime for example, so it's not really as required, but prevents a lot of instantiations you don't want.
Stackoverflow is littered with this kind of question. Take a look at this search. C# doesn't support a way to define a generic type constrained by numbers. Sadly, your best bet is to implement the extension method on all objects and do a switch based on type or to create a set of methods for ints, doubles, floats, etc.
It is hard to limit to just numerics, since there is nothing common like
INumeric
to use as the filter. Actually, I suspect the easiest approach here is to not insist on the constraint, and useComparer<T>.Default.Compare
inside the method.This inbuilt type supports both the generic
IComparable<T>
and the non-genericIComparable
, and supports ref-types, value-types and lifted usage viaNullable<T>
.For full operator usage, look at MiscUtil's
Operator
class andGreaterThan
etc, which may be useful if you really want to use the operator (rather than the interface). It also provides access to the other operators likeAdd
etc.