首页 > 解决方案 > 我怎样才能把这个简单的方法变成一个通用的方法?

问题描述

我有一个方法如下:

int coerce(int val, int min=0, int max = 10)
{
    if (val < min)
        return min;
    if (val > max)
        return max;
    return val;
}

现在,我必须将其用于bytefloatdouble和其他数字类型。

众所周知,为这些类型制作许多类似的方法是非常无效的,所以我想把它变成一个泛型方法。以下是我尝试做的事情:

T coerce<T>(T val, T min=(T)0, T max=(T)10) where T:IComparable
{
    // ... same as the above ...
}

我知道代码没有运行,这就是我要求这个的原因。我目前对两个问题感到困惑:

  1. 如何比较T类型?

    Visual Studio 会警告操作员<>. 我尝试使用where T:IComparable,但它并没有解决我的问题。

  2. 如何为泛型参数设置默认值?

    我尝试使用(T)0(T)10。但无论如何,这不是一个好的选择。

这可能是一个简单的问题,但我无法从谷歌找到答案。

标签: c#.netgenericscomparison-operators

解决方案


您应该使用Compare方法而不是<>运算符。并应用正确的通用约束,对于数字类型它应该是IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable. 但是,您可以只留下where T : struct, IComparable<T>,它应该足以满足您的目的(但struct在这里很重要,因为您正在比较值类型)

T coerce<T>(T val, T min, T max) where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
    if (val.CompareTo(min) < 0)
        return min;
    if (val.CompareTo(max) > 0)
        return max;

    return val;
}

您还可以指定默认min值,例如T min = default(T),但您不能为maxvalue 这样做。

在注释之后,如果使用Nullable<T>forminmaxvalues 代码可以写成

T coerce<T>(T val, T? min = default, T? max = default) where T : struct, IComparable<T>
{
    var minValue = min.HasValue ? min.Value : default(T);
    var maxValue = max.HasValue ? max.Value : (T)Convert.ChangeType(10, typeof(T));

    if (val.CompareTo(minValue) < 0)
        return minValue;
    if (val.CompareTo(minValue) > 0)
        return maxValue;

    return val;
}

推荐阅读