How to handle int and float in one class

L

Lee

I'd like to implement a generic class that takes as its Type-parameter
a numeric type (e.g. (U)Int16/32/64, float, double, decimal, etc.).

The problem is that, having validated the Type-parameter, I cannot do
any arithmetic operations (+, -, *, /) on variables of that type.

I tried creating wrapper-classes for the numeric types I will support
and tried to derive them from a custom interface that specified the
above 4 operators -- but interfaces are not allowed to specify
operators.

The only solution I can think of is to use a 'switch' statement at the
places I need to do the arithmetic operations -- but to me that is a
very poor solution.

I'm fairly sure this problem has arisen before and I'm hoping someone
can point me to a viable solution.
 
B

Barry Kelly

Lee said:
I'd like to implement a generic class that takes as its Type-parameter
a numeric type (e.g. (U)Int16/32/64, float, double, decimal, etc.).

The problem is that, having validated the Type-parameter, I cannot do
any arithmetic operations (+, -, *, /) on variables of that type.

I tried creating wrapper-classes for the numeric types I will support
and tried to derive them from a custom interface that specified the
above 4 operators -- but interfaces are not allowed to specify
operators.
I'm fairly sure this problem has arisen before and I'm hoping someone
can point me to a viable solution.

You need to use an abstract base class or (preferably) an interface that
defines the operations you want as methods. You can't do it just with
operators.

The general pattern is the same as with IComparer<T> and
IEqualityComparer<T> - these provide equivalents of '<' and '=='
respectively, in the form of Compare and Equals, respectively.

You then pass an implementation of your IArithmetic<T> to your generic
class's constructor, or methods that require such operations. If you do
it right, you can even avoid virtual / interface method calls:

---8<---
using System;

interface IArithmetic<T>
{
T Add(T l, T r);
}

struct Int32Arithmetic: IArithmetic<int>
{
public int Add(int l, int r) { return l + r; }
}

class App
{
static T Sum<T,TOps>(T[] array, TOps ops)
where TOps: IArithmetic<T>
{
T result = default(T);
foreach (T item in array)
result = ops.Add(result, item);
return result;
}

static void Main()
{
int[] values = { 10, 20, 30 };
Console.WriteLine(
Sum<int,Int32Arithmetic>(values,
new Int32Arithmetic()));
}
}
--->8---

The calls to ops.Add above are resolved statically due to (1) TOps being
constrained to an interface, (2) the implementation type specified
directly, and (3) the concrete implementation of the interface being on
a sealed type, such as a struct.

Obviously, if you're doing lots of this, you'll want to specify TOps &
ops in a descendant class & constructor, to avoid verbosity.

With appropriate reflection tricks, an equivalent to Comparer<T>.Default
(that might be called Arithmetic<T>.Default, for example) can be
created.

-- Barry
 
J

Jon Skeet [C# MVP]

I'd like to implement a generic class that takes as its Type-parameter
a numeric type (e.g. (U)Int16/32/64, float, double, decimal, etc.).

The problem is that, having validated the Type-parameter, I cannot do
any arithmetic operations (+, -, *, /) on variables of that type.

You'd probably find the Operator class in MiscUtil useful. MiscUtil is
a free library I've got: http://pobox.com/~skeet/csharp/miscutil

The Operator class is written by Marc Gravell.

See http://pobox.com/~skeet/csharp/miscutil/usage/genericoperators.html
for more details.

Jon
 
L

Lee

You'd probably find the Operator class in MiscUtil useful. MiscUtil is
a free library I've got:http://pobox.com/~skeet/csharp/miscutil

The Operator class is written by Marc Gravell.

Seehttp://pobox.com/~skeet/csharp/miscutil/usage/genericoperators.html
for more details.

Jon

Jon:

Thanks for the response.

I found the links you mentioned after posting my message (my bad for
not doing a more thorough search ahead of time :) -- I was about to
post that I found the ones you cited when I saw your response.)

Anyway, they are exactly what I am looking for.

Much thanks.
 
M

Marc Gravell

If you get any problems, let me know; I also have a 2.0 version
somewhere, but it isn't as complete nor unit tested.

Marc
 
J

Jon Skeet [C# MVP]

If you get any problems, let me know; I also have a 2.0 version
somewhere, but it isn't as complete nor unit tested.

We ought to do something about this - and the fact that it's currently
in MiscUtil, despite being a clearly desirable entity in its own
right. I think it may be time to start thinking about a
code.google.com project just for the operator stuff. The reason I'm
posting this instead of mailing it straight to Marc is that it would
be good to get more people involved. Quite how we then migrate it
*out* of MiscUtil is a different question, but we can tackle that
later.

Jon
 
M

Marc Gravell

No problem here; my only thought is that there isn't really much left to
do with it now (I can't envisage any huge changes / feature requests) so
it would mainly be a code dump, not an active project.

I like the employer-loyalty, though; last time we discussed this
(probably re the whole of MiscUtil), I'm sure you were talking about
another code site ;-p

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top