views:

714

answers:

8

Greets!

I'm attempting to set up a Cartesian coordinate system in C#, but I don't want to restrict myself to any one numerical type for my coordinate values. Sometimes they could be integers, and other times they could be rational numbers, depending on context.

This screams "generic class" to me, but I'm stumped as to how to constrict the type to both integrals and floating points. I can't seem to find a class that covers any concept of real numbers...

public class Point<T> where T : [SomeClassThatIncludesBothIntsandFloats?]  {
    T myX, myY;

    public Point(T x, T y) {
        myX = x;
        myY = y;
    }
}

Point<int> pInt = new Point<int>(5, -10);
Point<float> pFloat = new Point<float>(3.14159, -0.2357);

If I want this level of freedom, am I electing for a "typeof(T)" nightmare when it comes to calculations inside my classes, weeding out bools, strings, objects, etc? Or worse, am I electing to make a class for each type of number I want to work with, each with the same internal math formulae?

Any help would be appreciated. Thanks!

+5  A: 

This is a known problem, since none of the arithmetic classes arrive from the same class. So you cannot restrict it.

The only thing you could do is

where T : struct

but thats not exactly what you want.

Here is a link to the specific issue.

Arithmetic types like int,double,decimal should implement IArithmetic<T>

Stan R.
Hey Stan, just wanted to let you know that helps quite a bit. In a single stroke, making T inherit from struct eliminates the need for a run-time check for all value types. Thanks, bud!
Syndog
A: 

This might be helpful. You have to use a generic class to achieve what you want.

Jab
+4  A: 

You can't define such a constraint, but you could check the type at runtime. That won't help you for doing calculations though.

If you want to do calculations, something like this would be an option:

class Calculations<T, S> where S: Calculator<T>, new()
{
    Calculator<T> _calculator = new S();

    public T Square(T a)
    {
        return _calculator.Multiply(a, a);
    }

}

abstract class Calculator<T>
{
    public abstract T Multiply(T a, T b);
}

class IntCalculator : Calculator<int>
{
    public override int Multiply(int a, int b)
    {
        return a * b;
    }
}

Likewise, define a FloatCalculator and any operations you need. It's not particularly fast, though faster than the C# 4.0 dynamic construct.

var calc = new Calculations<int, IntCalculator>();
var result = calc.Square(10);

A side-effect is that you will only be able to instantiate Calculator if the type you pass to it has a matching Calculator<T> implementation, so you don't have to do runtime type checking.

This is basically what Hejlsberg was referring to in this interview where the issue is discussed. Personally I would still like to see some kind of base type :)

Thorarin
Right, that makes sense. Basically wrap my "primitive" types in classes that implement a common interface, then constrict based on that. Thanks, Thor!
Syndog
Note that in .NET 3.5 there are still things you can do with generics - see my answer for more.
Marc Gravell
A: 

C# doesn't currently allow type constraints on value types. i asked a related question not too long ago.

http://stackoverflow.com/questions/1331739/enum-type-constraints-in-c

Taylor Leese
A: 

Hmm, makes me wonder if there is a C# equivalent to the "union" keyword in C++

so you could just treat the same bytes as either int of float.

Perhaps keep the data internally as uint32/uint64 and cast to int/float as needed? MIght be too much overhead though.

Neil N
You can create a C# version of a union by using the StructLayout.Explicit and FieldOffset attributes.
Taylor Leese
@Taylor: do you have an example?
Neil N
Take a look at this: http://stackoverflow.com/questions/1182782/c-structlayout-explicit-question
Taylor Leese
A: 

Would this not lend itself to having seperate classes implementing IPoint?

Something like:

public interface IPoint<T>  
{
    T X { get; set; }
    T Y { get; set; }
}

public class IntegerPoint : IPoint<int>
{

    public int X { get; set; }
    public int Y { get; set; }
}

As the calculations will have to differ in each implementation anyway right?

Dan#

Daniel Elliott
Well, the calculations are actually identical, regardless of whether or not they're implemented using integer or floating-point values. Otherwise I'd just make two separate classes that implement their respective types without any generics or inheritance at all. But since the formulas are identical, I don't want to duplicate code between classes. Thanks for your response!
Syndog
+2  A: 

You actually can do this, although the solution is tedious to set up, and can be confusing to devs who are not awaare of why it was done. (so if you elect to do it document it thououghly!)...

Create two structs, called say, MyInt, and MyDecimal which act as facades to the CTS Int32, and Decimal core types (They contain an internal field of that respective type.) Each should have a ctor that takes an instance of the Core CTS type as input parameter..

Make each one implement an empty interface called INumeric

Then, in your generic methods, make the constraint based upon this interface. Downside, everywhere you want to use these methods you have to construct an instance of the appropriate custom type instead of the Core CTS type, and pass the custom type to the method.

NOTE: coding the custom structs to properly emulate all the behavior of the core CTS types is the tedious part... You have to implement several built-in CLR interfaces (IComparable, etc.) and overload all the arithmetic, and boolean operators...

Charles Bretana
+1  A: 

This is a very common question; if you are using .NET 3.5, there is a lot of support for this in MiscUtil, via the Operator class, which supports inbuilt types and any custom types with operators (including "lifted" operators); in particular, this allows use with generics, for example:

public static T Sum<T>(this IEnumerable<T> source) {
    T sum = Operator<T>.Zero;
    foreach (T value in source) {
        if (value != null) {
            sum = Operator.Add(sum, value);
        }
    }
    return sum;
}

Or for another example; Complex<T>

Marc Gravell
Interesting. Looks like it uses the LINQ expression tree functionality, but immediately evaluates each bit?
Thorarin
Internally, it uses an expression tree to pre-compile (once-only per-type) a delegate that can do the arithmetic.
Marc Gravell