电贺!
我正在尝试在C#中设置笛卡尔坐标系,但我不想将自己限制为我的坐标值的任何一种数值类型。有时它们可能是整数,有时它们可能是有理数,取决于上下文。
这对我来说是“通用类”,但我对如何将类型限制为积分和浮点感到难过。我似乎无法找到涵盖任何实数概念的课程......
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);
如果我想要这种自由度,那么当我在课堂上进行计算,除去bool,字符串,对象等时,我是否选择了“typeof(T)”噩梦?或者更糟糕的是,我是否选择为我想要使用的每种类型的数字创建一个类,每个都有相同的内部数学公式?
任何帮助将不胜感激。谢谢!
答案 0 :(得分:16)
您无法定义此类约束,但可以在运行时检查类型。但这对你的计算没有帮助。
如果你想进行计算,可以选择这样的选项:
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;
}
}
同样,定义FloatCalculator
以及您需要的任何操作。虽然比C#4.0 dynamic
构造更快,但速度并不是特别快。
var calc = new Calculations<int, IntCalculator>();
var result = calc.Square(10);
副作用是,如果传递给它的类型具有匹配的Calculator
实现,则只能实例化Calculator<T>
,因此您不必执行运行时类型检查。
这基本上是Hejlsberg在讨论问题的this interview中提到的内容。就个人而言,我仍然希望看到某种基本类型:)
答案 1 :(得分:12)
这是一个非常常见的问题;如果您使用的是.NET 3.5,那么MiscUtil中有很多支持,通过Operator
类,它支持内置类型和任何带有运算符的自定义类型(包括“提升”运算符);特别是,这允许与泛型一起使用,例如:
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;
}
或者另一个例子; Complex<T>
答案 2 :(得分:7)
这是一个已知问题,因为没有一个算术类来自同一个类。所以你不能限制它。
你唯一能做的就是
where T : struct
但这不完全是你想要的。
以下是特定问题的链接。
Arithmetic types like int,double,decimal should implement IArithmetic<T>
答案 3 :(得分:3)
你实际上可以做到这一点,虽然解决方案设置起来很繁琐,并且可能会让那些不知道为什么会这样做的开发人员感到困惑。 (所以,如果你选择这样做,那就完全记录下来了!)......
创建两个结构,名为say,MyInt和MyDecimal,它们充当CTS Int32的外观,以及十进制核心类型(它们包含相应类型的内部字段。)每个结构都应该有一个ctor,它接受一个实例核心CTS类型作为输入参数..
使每个实现一个名为INumeric
的空接口然后,在您的泛型方法中,根据此接口创建约束。 在下方,除了要使用这些方法之外,还必须构造适当的自定义类型的实例而不是Core CTS类型,并将自定义类型传递给方法。
注意:编写自定义结构以正确模拟核心CTS类型的所有行为是繁琐的部分......您必须实现几个内置的CLR接口(IC Comparable等)并重载所有算法,并且布尔运算符...
答案 4 :(得分:1)
您可以更加接近实施更多
public class Point<T> where T : struct, IComparable, IFormattable, IConvertible,
IComparable<T>, IEquatable<T> {
}
签名也符合DateTime
。我不确定您是否能够从框架中指定更多类型。无论如何,这只能解决部分问题。要执行基本数值运算,您必须包装数字类型并使用泛型方法而不是标准运算符。 See this SO question有几个选项。
答案 5 :(得分:0)
Thi可能会有所帮助。你必须使用泛型类来实现你想要的目标。
答案 6 :(得分:0)
C#目前不允许对值类型进行类型约束。我不久前问了一个相关的问题。
答案 7 :(得分:0)
这不适合实现IPoint的单独类吗?
类似的东西:
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; }
}
因为每次实施的计算都必须不同吗?
丹#