I'm trying to write classes which handle different number types. I know that C# (and .Net in general, I believe) has no INumber
interface, so I cannot use something like the following:
public class Adder<T> where T:INumber
{
public T Add(T a, T b)
{
return a + b;
}
}
That's okay, though, because I'd like to avoid the boxing/unboxing of every one of my numbers. I could, however, use conditional compilation for each type I want to support:
#if FLOAT
public class AdderF
{
public float Add(float a, float b)
#else
public class Adder
{
public int Add(int a, int b)
#endif
{
return a + b;
}
}
This means I'll need to compile a different Library.dll
and LibraryF.dll
, however. Is there any more elegant solution to this?
Obviously, in my example, I can simply write the code twice. I would like to use this process, however, to create large complicated data structures with an integer version and floating-point version, so do not want the possibility of copy-paste errors when updating my structure. Nor do I want the speed loss from wrapping the floating-point structure in an integral-wrapper, and unnecessarily converting all inputs to the more lenient data type.
I guess it depends on how strict you want it to be. Do you want an Add
method that only takes two parameters of the exact same type (int and int, float and float) ... ? If not, and performance is not super-important, then you can just implement your solution with decimal
and it will all work.
If it does have to be strict, and you want specific versions per type, you may want to look into T4 code generation. It's akin to C++'s templates (some people think C++ templates and C# generics are the same, but they're not).
Scott Hanselman wrote an interesting article about it.
Maybe this could be useful: Is there a C# generic constraint for "real number" types?.
It seems that it's not directly possible as you have said. It would be useful to have it.
The main challenge here is that the jitter has to emit different opcodes depending on whether you're adding floats or ints, so, even though the code looks similar, it's actually quite different behind the scenes. This is doable in C++ (because templates are compiled separately for each type definition), but .NET generics work differently. Take a look at T4 templates as one possible solution (if you really need the ability to compile as float or int separately.)
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