小编典典

是否存在将我的泛型方法限制为数字类型的约束?

all

谁能告诉我泛型是否有办法将泛型类型参数限制为T

  • Int16
  • Int32
  • Int64
  • UInt16
  • UInt32
  • UInt64

我知道where关键字,但找不到 仅适用 于这些类型的接口,

就像是:

static bool IntegerFunction<T>(T value) where T : INumeric

阅读 110

收藏
2022-03-21

共1个答案

小编典典

C# 不支持这一点。Hejlsberg在接受 Bruce Eckel
的采访时
描述了不实施该功能的原因:

而且还不清楚增加的复杂性是否值得您获得的少量收益。如果约束系统不直接支持你想做的事情,你可以用工厂模式来做。例如,您可能有一个Matrix<T>,并且Matrix您想在其中定义一个点积方法。这当然意味着你最终需要了解如何将两个Ts
相乘,但你不能说这是一个约束,至少不是 if Tis int, double, or
float。但是你可以做的是将你的Matrix取值作为一个参数Calculator<T>,并且在Calculator<T>其中有一个名为
的方法multiply。你去实现它并将它传递给Matrix.

然而,这会导致相当复杂的代码,用户必须为他们想要使用的每个提供自己的Calculator<T>实现。T只要它不是必须是可扩展的,即如果你只想支持固定数量的类型,例如intand
double,你可以使用一个相对简单的接口:

var mat = new Matrix<int>(w, h);

GitHub Gist
中的最小实现。

但是,一旦您希望用户能够提供他们自己的自定义类型,您就需要打开此实现,以便用户可以提供他们自己的Calculator实例。例如,要实例化一个使用自定义十进制浮点实现的矩阵DFP,您必须编写以下代码:

var mat = new Matrix<DFP>(DfpCalculator.Instance, w, h);

‘ 并执行所有成员为DfpCalculator : ICalculator<DFP>

正如所讨论的,另一种方法(不幸的是具有相同的限制)是使用策略类。
使用策略的解决方法:

interface INumericPolicy<T>
{
    T Zero();
    T Add(T a, T b);
    // add more functions here, such as multiplication etc.
}

struct NumericPolicies:
    INumericPolicy<int>,
    INumericPolicy<long>
    // add more INumericPolicy<> for different numeric types.
{
    int INumericPolicy<int>.Zero() { return 0; }
    long INumericPolicy<long>.Zero() { return 0; }
    int INumericPolicy<int>.Add(int a, int b) { return a + b; }
    long INumericPolicy<long>.Add(long a, long b) { return a + b; }
    // implement all functions from INumericPolicy<> interfaces.

    public static NumericPolicies Instance = new NumericPolicies();
}

算法:

static class Algorithms
{
    public static T Sum<P, T>(this P p, params T[] a)
        where P: INumericPolicy<T>
    {
        var r = p.Zero();
        foreach(var i in a)
        {
            r = p.Add(r, i);
        }
        return r;
    }

}

用法:

int i = NumericPolicies.Instance.Sum(1, 2, 3, 4, 5);
long l = NumericPolicies.Instance.Sum(1L, 2, 3, 4, 5);
NumericPolicies.Instance.Sum("www", "") // compile-time error.

该解决方案是编译时安全的。CityLizard Framework为 .NET 4.0 提供编译版本。该文件是 lib/NETFramework4.0/CityLizard.Policy.dll。

它也可以在 Nuget 中使用:https ://www.nuget.org/packages/CityLizard/ 。请参阅CityLizard.Policy.I结构。

2022-03-21