是否有一个“实数”types的C#通用约束?
可能重复:
C#通用约束只有整数
映入眼帘!
我正在尝试在C#中设置一个笛卡尔坐标系,但是我不想将自己的坐标值限制为任何一种数字types。 有时他们可能是整数,有时他们可能是有理数,取决于上下文。
这尖叫“generics类”给我,但我不知道如何将types收敛到积分和浮点。 我似乎无法find一个涵盖任何实数概念的类。
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);
如果我想要这样的自由度,当我在课堂上进行计算时,是否会select“type(T)”的噩梦,除去布尔,string,对象等? 或者更糟糕的是,我是否select为每个想要使用的数字types创build一个类,每个类都使用相同的内部math公式?
任何帮助,将不胜感激。 谢谢!
你不能定义这样的约束,但你可以在运行时检查types。 这不会帮助你做计算。
如果你想做计算,这样的事情将是一个select:
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);
副作用是,如果传递给它的types具有匹配的Calculator<T>
实现,则只能实例化Calculator
,因此不必执行运行时types检查。
基本上这就是Hejlsberg在这次采访中提到的问题。 我个人还是希望看到某种基types:)
这是一个很常见的问题。 如果你使用.NET 3.5,在MiscUtil中有很多支持,通过Operator
类,它支持内置types和任何自定义types的运营商(包括“提升”的运营商)。 特别是,这允许与generics一起使用,例如:
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>
这是一个已知的问题,因为没有一个算术类来自同一个类。 所以你不能限制它。
你唯一能做的就是
where T : struct
但那不完全是你想要的。
这是一个特定问题的链接。
像int,double,decimal这样的算术types应该实现IArithmetic <T>
实际上,你可以做到这一点,虽然解决方法是繁琐的设置,可能会让开发人员不知道为什么这样做。 (所以如果你select这样做的话,它会很好地!)…
创build两个名为say,MyInt和MyDecimal的结构,它们作为CTS Int32的外观,以及Decimal核心types(它们包含相应types的内部字段)。每个结构都应该有一个采用Core CTStypes实例的ctor作为input参数..
使每个实现一个名为INumeric的空接口
然后,在你的generics方法中,根据这个接口进行约束。 不利的一点是,在任何想要使用这些方法的地方,都必须构build适当的自定义types的实例,而不是Core CTStypes,并将自定义types传递给方法。
注意:对自定义结构进行编码以正确模拟核心CTStypes的所有行为是单调乏味的部分…您必须实现多个内置的CLR接口(IComparable等),并重载所有算术和布尔运算符。 ..
你可以靠近几个实施
public class Point<T> where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> { }
签名也符合DateTime
。 我不确定您是否能够从框架中指定更多的types。 无论如何,这只能解决部分问题。 要进行基本的数字操作,您将不得不包装数字types,并使用generics方法而不是标准操作符。 看到这个问题的几个选项。
这可能会有所帮助。 你必须使用一个通用的类来实现你想要的。
C#当前不允许在值types上使用types约束。 我不久前问了一个相关的问题。
C#中的枚举types约束
这不适合分开实施IPoint的课程吗?
就像是:
public interface IPoint<T> { TX { get; set; } TY { get; set; } } public class IntegerPoint : IPoint<int> { public int X { get; set; } public int Y { get; set; } }
因为计算将不得不在每个实施方面有所不同吗?
担#