简体   繁体   English

单个泛型上的可比较和可空约束

[英]Comparable and Nullable constraints on single generic

I want to write an extension method which compares a value against two other values and determines if the value is within the other two. 我想编写一个扩展方法,将一个值与其他两个值进行比较,并确定该值是否在其他两个值之内。 This works for that purpose 为此目的

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);
}

I would also like to extend this method to work on Nullable<T> . 我也想扩展此方法以在Nullable<T> I would like either boundary condition to be ignored if the value is null. 如果该值为空,我希望忽略任何一个边界条件。 I have tried putting an additional constraint on T, but this is not supported. 我尝试对T设置其他约束,但是不支持此约束。 The following code doesn't compile, but is what I want to achieve. 以下代码无法编译,但是我想要实现。

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));
}

Is it possible write a single method which achieves this? 是否可以编写一个实现该目标的方法?

You need to constrain T to be a struct to match the definition of Nullable<T> : 您需要将T约束为一个struct以匹配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);
}

You also need to use .Value to get the T from the Nullable<T> . 您还需要使用.ValueNullable<T>获取T

As SLaks answered, the reason Nullable<T> (or just T? ) isn't accepted is because that requires T to be a non-nullable value type. 正如SLaks回答的那样,未接受Nullable<T> (或只是T? )的原因是因为这要求T为非空值类型。 You cannot use a single method that covers value and reference types alike: the value types you want to support can't represent null , and reference types can't support T? 您不能使用覆盖值和引用类型的单一方法:要支持的值类型不能表示null ,而引用类型不能支持T? , so you can't avoid having two separate methods. ,因此您不可避免地要避免使用两种单独的方法。

However, you can use the exact same function body twice, to make it obvious to a reader that the two overloads do the same thing: 但是,您可以使用完全相同的函数体两次,以使读者明显知道这两个重载可以完成相同的操作:

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM