单一泛型的可比较和可空约束

时间:2015-04-15 21:53:17

标签: c# generics extension-methods nullable

我想编写一个扩展方法,将一个值与另外两个值进行比较,并确定该值是否在另外两个值之内。这适用于此目的

public static bool IsWithin<T>(this T value, T min, T max) where T : IComparable<T>
{
    return (bool)(value.CompareTo(min) > 0 && value.CompareTo(max) < 0);
}

我还希望将此方法扩展到Nullable<T>。如果值为null,我想要忽略边界条件。我已经尝试在T上添加一个额外的约束,但这不受支持。以下代码无法编译,但是我想要实现。

public static bool IsWithinInclusive<T>(this T value, Nullable<T> min, Nullable<T> max) where T : IComparable<T>
{
    return (bool)(
        (min.HasValue ? value.CompareTo(min) >= 0 : true) && 
        (max.HasValue ? value.CompareTo(max) <= 0 : true));
}

是否可以编写一个实现此目的的方法?

2 个答案:

答案 0 :(得分:4)

您需要将T限制为struct以匹配definition of Nullable<T>

public static bool IsWithinInclusive<T>(this T value, Nullable<T> min, Nullable<T> max) where T : struct, IComparable<T>
{
    return 
        (min.HasValue ? value.CompareTo(min.Value) >= 0 : true) && 
        (max.HasValue ? value.CompareTo(max.Value) <= 0 : true);
}

您还需要使用.ValueT获取Nullable<T>

答案 1 :(得分:2)

正如SLaks所回答的那样,Nullable<T>(或仅T?)被接受的原因是因为这需要T为非可空值类型。您不能使用涵盖值和引用类型的单一方法:您要支持的值类型不能代表null,而引用类型也不能支持T?,所以你不能避免使用两种不同的方法。

但是,你可以两次使用完全相同的函数体,让读者明白这两个重载做同样的事情:

public static bool IsBetween<T>(this T value, T min, T max) where T : IComparable<T>
{
    return (min == null || value.CompareTo((T)min) >= 0)
        && (max == null || value.CompareTo((T)max) <= 0);
}

public static bool IsBetween<T>(this T value, T? min, T? max) where T : struct, IComparable<T>
{
    return (min == null || value.CompareTo((T)min) >= 0)
        && (max == null || value.CompareTo((T)max) <= 0);
}