Doing arithmetic on generic parameters

I'd like to write methods that perform arithmetic operations on generic (but numeric) parameters.

The following code produces compiler error CS0019

public T Add<T> (T a, T b)
{
return
a + b;
}

while this produces compiler error CS0072

public T Add<T> (T a, T b) where T:ValueType
{
return
a + b;
}

Can this be done?

[1168 byte] By [dba] at [2008-2-7]
# 1

Only for you. Only today ;-)

using System;
using System.Reflection;

namespace TestApp
{
class My
{
public static My operator +(My x, My y)
{
return x;
}
}

public static class PrimiteImpl
{
// Define operations here for all primitive classes
public static int Add(int x, int y)
{
return x + y;
}
}
public static class MathOps<T>
{

delegate T BinaryOp(T a, T b);
static readonly BinaryOp add;
static MathOps()
{
// For primitive types we need to emulate this functionality manualy
if (typeof(T).IsPrimitive)
{
add = (BinaryOp)Delegate.CreateDelegate(typeof(BinaryOp), typeof(PrimiteImpl), "Add", false, false);
}
else
{
// For user-defined custom types - use type from user
add = (BinaryOp)Delegate.CreateDelegate(typeof(BinaryOp), typeof(T), "op_Addition", false, false);
}
// If not found do not leave our delegate as empty to avoid useless null-checks
// but assign it to method that will throw some valuable information to user
// It's up to you to use this hack or throw some custom exception as early as possible
if (add == null)
{
add = new BinaryOp(NotSupported);
}
}
// Requered to avoid TypeInitializationException then no operation can be found
private static T NotSupported(T dummy1, T dummy2)
{
throw new NotSupportedException(string.Format("I'm realy sorry. {T} does not support some requered operations.",typeof(T).FullName));
}
public static T Add(T x, T y)
{
return add(x, y);
}
}

class Program
{
public static T Add<T>(T a, T b)
{
return MathOps<T>.Add(a, b);
}
static void Main(string[] args)
{
int x = 10;
int y = 20;
int z = Add(x, y);
My a = new My();
My b = Add(a, a);
long implementMePlz = Add<long>(1, 2);
}
}
}

TAG at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 2
Thanks, I think.

I trimmed my example down to a trivial task. What I really want to do is some fairly sophisticated mathematical operations on 2- and 3-dimensional arrays of data for a CAT-scan reconstructor. But I'd like to be able to operate using either single- or double-precision floating-point values.

With C++, I could make templates that did the math using standard operators, and then instantiate them using whatever data type I liked. I assumed that C# generics would give me the same capability.

If I have to go as much trouble as you indicate, and give up using standard math operators, it will be easier just to write multiple versions of the functions.

What a disappointment! Is this really the best C# can provide?

Thanks anyway. I do appreciate the effort. Anybody else have a better idea?

dba at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 3
I think I found the answer, and it was not what I hoped for. In the 2005 Beta2 documentation page titled:

Differences Between C++ Templates and C# Generics (C# Programmers Reference)

is the following:

C# generics do not provide the same amount of flexibility as C++ templates. For example, it is not possible to call arithmetic operators in a C# generic class, although it is possible to call user defined operators.

Bummer!

dba at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 4
If you need only two, three or some limited number of classes supported (I think you have mentioned that you need double and float only) - then simply code all of them and compile in your assembly.

To do this easily you can use combination of partial classes, C++ macros and preprocessor.

Create a source code for your class / functions like this one:
MyFunctions.cs.tmpl

partial class MyFunctions {
RET_TYPE DoFoo(RET_TYPE x, RET_TYPE y) {
return x+y;
}
}

Then proprocess by C++ preprocessor with correct types like a:
cl -E -D RET_TYPE=double MyFunctions.cs.tmpl > MyFuntions.double.cs

Add all thouse generated sources to project.
To make this automaticaly you can batch script that will do this as pre-build event (Project -> Properties -> Build Events)

As partial modifier was used - all functions will reside in same class and correct overloads will be selected automaticaly.

P.S> As well you can take a look on C++/CLI that will allow to generate .NET IL code with C++ syntax.

Hope this helps.

TAG at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 5

Sorry for such a compicated example.

You do with a little bit simpler with help of "using" statements:

using T = System.Double;

class MyFunctions
{
T DoFoo(T x, T y)
{
return x+y;
}
}

All you need now is to keep sources with different using statements in sync.

TAG at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 6
You might want to check this page at CodeProject.
HTH,

ChrisJ.Breisch at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...