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.)
Declaring those constraints means you can use the operations and method calls of the constraining type. If your generic class or method uses any operation on the generic members beyond simple assignment or calling any methods not supported by System. Object, you'll apply constraints to the type parameter.
Interface Type Constraint You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.
To enable two objects of a generic type parameter to be compared, they must implement the IComparable or IComparable<T>, and/or IEquatable<T> interfaces. Both versions of IComparable define the CompareTo() method and IEquatable<T> defines the Equals() method.
In this case you want to constrain your generic to the IComparable
interface, which gives you access to the CompareTo
method, since this interface allows you to answer the question ShouldBeGreaterThan
.
Numeric types will implement that interface and the fact that it also works on strings shouldn't bother you that much.
where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With