为什么数字类型不共享通用接口?

Jen*_*ens 27 c#

我最近遇到了这个问题,我想要一个函数来处理双精度和整数,并且想知道为什么所有数字类型都没有通用接口(包含算术运算符和比较).

它会使编写函数Math.Min(存在于无数的重载中)更方便.

引入一个额外的接口是一个突破性的变化吗?

编辑: 我想考虑使用这个

public T Add<T>(T a, T b) where T: INumber
{
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

要么

public T Range<T>(T x, T min, T max) where T:INumber
{
    return Max(x, Min(x, max), min);
}
Run Code Online (Sandbox Code Playgroud)

Dir*_*mar 8

如果你想做这种"通用"算术,你选择强类型语言如C#是非常有限的.Marc Gravell 将问题描述如下:

.NET 2.0在.NET世界中引入了泛型,为现有问题的许多优雅解决方案打开了大门.通用约束可以用来限制类型参数已知接口等,以确保获得的功能-或者简单的等号/不等测试Comparer<T>.DefaultEqualityComparer<T>.Default 单身落实IComparer<T>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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您应该知道这会消除类型安全性,如果动态运行时无法找到合适的调用重载,您可能会在运行时获得异常,例如因为您混合了类型.

如果您想获得类型安全性,您可能需要查看MiscUtil库中可用的类,为基本操作提供通用运算符.

请注意,如果您仅在特定操作之后,实际上可能使用内置类型已实现的接口.例如,类型安全的泛型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;
}
Run Code Online (Sandbox Code Playgroud)

  • 你的泛化是很好的方法,但是它不支持特定的`Add`方法,它只对可比较的动作有用,不适用于数字中所有可能的动作,而动态因其速度而不是好方法. (2认同)