我想写一个可以接受任何数字的C#方法。类似的东西:
public static T Sum(T a, T b) where T : number { // (not real code)
return a + b;
}
但我没有在C#中看到一个“数字”基类,就像我用过的大多数其他语言一样。数值类型是IComparable,IFormattable,IConvertible,IComparable和IEquatable,但似乎没有任何算术功能。它们都是结构,除了物体外没有明显的共同超类。 (请原谅我,如果我搞砸了这里的意思,因为我不太熟悉C#结构,以及它们的所有方式或类似的方式。)
我是否遗漏了某些内容,或者是否无法在C#中编写一个执行“a + b”的方法而没有在“+”的上下文中明确指出a和b是什么?
答案 0 :(得分:4)
您将不得不求助于使用重载。有点像Math
类正在使用像Math.Max
这样的函数,它支持所有数字类型。
CD提出的link也足智多谋。
答案 1 :(得分:3)
有关类似的讨论,请参阅this SO question。
此外,如果您愿意为要使用它的每个.Net核心数类型创建单独的类型,您可以执行此操作(需要一些繁琐的工作)。
创建两个结构,名为say,MyInt和MyDecimal,它们充当CTS Int32的外观,以及十进制核心类型(它们包含相应类型的内部字段。)每个结构都应该有一个ctor,它接受一个实例核心CTS类型作为输入参数..
使每个实现一个名为INumeric
的空接口然后,在您的泛型方法中,根据此接口创建约束。在下方,除了要使用这些方法之外,还必须构造适当的自定义类型的实例而不是Core CTS类型,并将自定义类型传递给方法。
注意:编写自定义结构以正确模拟核心CTS类型的所有行为是繁琐的部分......您必须实现几个内置的CLR接口(IC Comparable等)并重载所有算法,并且布尔运算符...
答案 2 :(得分:2)
不幸的是,不存在这样的类/接口。
答案 3 :(得分:2)
int和其他数值类型是ValueTypes。如前所述,你所能做的只是说where T: struct
。好吧,您可以使用反射来检查类型参数是否实现了添加......但我不确定这是不是一个好主意。
答案 4 :(得分:0)
你能做的最好的是where T : struct
,它需要一个ValueType;所有数字都是ValueTypes。
不幸的是,所有用户定义的结构都是如此,所以这就是缺点。没有特定的泛型可以接受所有数字类。
我甚至不建议这样做,但你可能考虑对方法中T
的类型进行运行时检查,如果T
不是int,则抛出,long,短,浮动或双重。不幸的是,这对编程时的程序员没有帮助。
答案 5 :(得分:0)
这是一个非常常见的问题;如果您使用的是.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>