Update
通用数学将作为 .NET 6 的预览功能提供。请阅读 .NET 开发博客中的公告:
https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/ https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/
如果您想做这种“通用”算术,那么强类型语言(例如 C#)的选择非常有限。马克·格拉维尔问题描述如下 http://www.yoda.arachsys.com/csharp/genericoperators.html:
.NET 2.0 将泛型引入了 .NET 世界,这为许多现有问题的优雅解决方案打开了大门。通用约束可用于将类型参数限制为已知接口等,以确保对功能的访问 - 或者对于简单的相等/不等式测试Comparer<T>.Default
and EqualityComparer<T>.Default
单例实现IComparer<T>
and IEqualityComparer<T>
分别(例如,允许我们对元素进行排序,而不必了解有关“T”的任何信息)。
尽管如此,在运营商方面仍然存在很大差距。因为运算符被声明为静态方法,所以没有IMath<T>
或所有数字类型实现的类似等效接口;事实上,运营商的灵活性使得这很难以有意义的方式做到这一点。更糟糕的是:许多基本类型上的运算符甚至不作为运算符存在;相反,有直接的 IL 方法。为了使情况变得更加复杂,Nullable 需要“提升运算符”的概念,其中内部“T”描述适用于可空类型的运算符 - 但这是作为语言功能实现的,并且不是由运行时(使反射更加有趣)。
然而,C# 4.0 引入了dynamic
您可以使用关键字在运行时选择正确的重载:
using System;
public class Program
{
static dynamic Min(dynamic a, dynamic b)
{
return Math.Min(a, b);
}
static void Main(string[] args)
{
int i = Min(3, 4);
double d = Min(3.0, 4.0);
}
}
您应该意识到,这会消除类型安全性,并且如果动态运行时找不到合适的重载来调用,您可能会在运行时遇到异常,例如因为你混合了类型。
如果您想获得类型安全,您可能需要查看以下可用的类MiscUtil http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html库为基本操作提供通用运算符。
请注意,如果您仅执行特定操作,您实际上可能会使用内置类型已经实现的接口。例如,类型安全的泛型Min
函数可能如下所示:
public static T Min<T>(params T[] values) where T : IComparable<T>
{
T min = values[0];
foreach (var item in values.Skip(1))
{
if (item.CompareTo(min) < 0)
min = item;
}
return min;
}