Possible Duplicate:
C# generic constraint for only integers
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!
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 :)
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>
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>
You actually can do this, although the solution is tedious to set up, and can be confusing to devs who are not aware 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...
You can get closer with implementing few more
public class Point<T> where T : struct, IComparable, IFormattable, IConvertible,
IComparable<T>, IEquatable<T> {
}
The signature conforms to DateTime too. I'm not sure if you will be able to specify more types from the framework. Anyway this only solves part of the problem. To do basic numeric operations you will have to wrap your numeric types and use generic methods instead of standard operators. See this SO question for a few options.
This might be helpful. You have to use a generic class to achieve what you want.
C# doesn't currently allow type constraints on value types. i asked a related question not too long ago.
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#
来源:https://stackoverflow.com/questions/1348594/is-there-a-c-sharp-generic-constraint-for-real-number-types