Is There a C# Generic Constraint for "Real Number" Types

Is there a C# generic constraint for real number types?

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 :)

Generic constraint to match numeric types

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.

Is there a constraint that restricts my generic method to numeric types?

This constraint exists in .Net 7.

Check out this .NET Blog post and the actual documentation.

Starting in .NET 7, you can make use of interfaces such as INumber and IFloatingPoint to create programs such as:

using System.Numerics;

Console.WriteLine(Sum(1, 2, 3, 4, 5));
Console.WriteLine(Sum(10.541, 2.645));
Console.WriteLine(Sum(1.55f, 5, 9.41f, 7));

static T Sum<T>(params T[] numbers) where T : INumber<T>
{
T result = T.Zero;

foreach (T item in numbers)
{
result += item;
}

return result;
}

INumber is in the System.Numerics namespace.

There are also interfaces such as IAdditionOperators and IComparisonOperators so you can make use of specific operators generically.

Is there a generic numeric type in C#?

No, there is not. Generics and arithmetic operations (+, -, *, /, etc.) simply do not work together. This is an issue that is brought up many times and the C# design comitee has never addressed (to be fair, this feature would need work on the CLR too, as pointed out by Eric Lippert in answer linked further on).

Curisously, if you inspect the source code of the .NET Framework you'll see that in some stage of development there was an IArithmetic<T> interface, but it was scrapped; see here.

You can read more about it, in this SO answer.

Generics - where T is a number?

What version of .NET are you using? If you are using .NET 3.5, then I have a generic operators implementation in MiscUtil (free etc).

This has methods like T Add<T>(T x, T y), and other variants for arithmetic on different types (like DateTime + TimeSpan).

Additionally, this works for all the inbuilt, lifted and bespoke operators, and caches the delegate for performance.

Some additional background on why this is tricky is here.

You may also want to know that dynamic (4.0) sort-of solves this issue indirectly too - i.e.

dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect

Re the comment about < / > - you don't actually need operators for this; you just need:

T x = ..., T y = ...
int c = Comparer<T>.Default.Compare(x,y);
if(c < 0) {
// x < y
} else if (c > 0) {
// x > y
}

Any elegant way to operate with generic types?

If Eric ever reads this,

If you want something brought to my attention, try the contact link on my blog. Or put my full name in the text of the question so that me searching for myself will find me.

does this feature (constraining generic types by defined operators) ever come up in hypothetical future versions of C# design meetings and has it ever been close to making it into the language?

Indeed, this is a frequently requested feature. We've been getting requests for this sort of thing since C# 1.0.

The feature would requires support from the CLR team, not just the language -- it is the sort of feature that we would want to integrate into all our languages, which increases the cost.

The CLR team has expressed interest in features like this, but they also have a lot of competing features that they could be doing, and limited time and effort to implement those features.

There are numerous ways such a feature could be implemented. For example, we could add the ability to specify static methods in interfaces:

interface IAddable<T>
{
static T operator+(T x, T y);
}

and then

static T Sum<T>(IEnumerable<T> seq) where T : IAddable<T>
{
T sum = default(T);
foreach(T item in seq) sum = sum + item;
return sum;
}

The idea would be that the interface means "a type that implements this interface must have the given static methods". We'd then make int automatically implement IAddable<int>, and so on.

How do do so efficiently in a world with runtime-generated generic code is an open question.

I hasten to add that this is just a sketch of an idea. There are many ways to implement this sort of feature. The "statics in interfaces" idea is one that has broader usage than just mathematics, and that's attractive to us. If we're going to go to the huge expense of this sort of feature, it would be nice to have a really general, powerful feature rather than one narrowly focussed on math.

On the other hand, the perfect is the enemy of the good; it might be better to just concentrate on the math problem and not go for a more expensive general solution.

It's an ongoing debate. It is definitely on everyone's radar screen, but I would not expect it any time soon. The language designers are all heads-down working on going through the feedback from the async CTP.

As always, Eric's musings about hypothetical future language features of hypothetical unannounced future products are for entertainment purposes only.

Is there a way to have a generic type constraint that is also generic?

Yes you could have two generic types

public abstract class RankUnlockedItemContainer<TItem, TValue> : ScriptableObject : where TItem : RankUnlockedItemBase<TValue> { ... }

And implement e.g.

[Serializable]
public class RankUnlockedIntContainer : RankUnlockedItemContainer<RankUnlockedInt, int> { ... }

Generic Structure - How to Constrain Type Parameter C#

You cannot do this, not this way.

C# does not know anyhting about generic type T. Is it a number? Is it a string? Can you do math with it?

If you want to get this working, you have to use a generic calculator. You must build it yourself. For more info, take a look at: http://www.codeproject.com/Articles/8531/Using-generics-for-calculations

A simpler solution could be:

a.v1 = Convert.ChangeType(Convert.ToDecimal(a.v1) * Convert.ToDecimal(b), typeof(T));

EDIT

I created a few library functions on another location. You can use this to implement in your own code. Calculating with these numbers would be easy. Your Vector-class would be:

partial struct Vector4D<T>
where T: IComparable<T>, IEquatable<T>
{
public Number<T> v1;
public Number<T> v2;
public Number<T> v3;
public Number<T> v4;

public static Vector4D<T> operator *(Vector4D<T> a, T b)
{
a.v1 *= b;
a.v2 *= b;
a.v3 *= b;
a.v4 *= b;
return a;
}
}

See: https://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number



Related Topics



Leave a reply



Submit