与 IComparable 一起使用的可空泛型类型。是否可以?

发布于 2024-09-10 20:32:49 字数 719 浏览 5 评论 0原文

我正在尝试创建一个简单的 Clamp (这样我就可以绑定任何可比较的值......主要针对 int、double 等数字类型)。

问题是,如果我执行以下操作,则会出现错误,但是根据 MSDN IComparable 的 CompareTo 应该能够处理空值。
Quote: “根据定义,任何对象都比较大于 null,并且两个 null 引用比较彼此相等。”

public static T Clamp<T>(this T value, T min, T max)
    where T : IComparable<T>
{
    if (value.CompareTo(max) > 0)
        return max;

    if (value.CompareTo(min) < 0)
        return min;

    return value;
}



private Int32? _zip;
public Int32? Zip
{
    get
    {
        return _zip;
    }
    set
    {
        _zip = value.Clamp<Int32?>(0, 99999);
    }
}

I'm trying to create a simple Clamp (so that I can bound the values of anything comparable ... mostly for number types such as int, double, etc.)

The problem is if I do the following I get an error, but according to MSDN IComparable's CompareTo is supposed to be able to handle null values.
Quote: "By definition, any object compares greater than null, and two null references compare equal to each other."

public static T Clamp<T>(this T value, T min, T max)
    where T : IComparable<T>
{
    if (value.CompareTo(max) > 0)
        return max;

    if (value.CompareTo(min) < 0)
        return min;

    return value;
}



private Int32? _zip;
public Int32? Zip
{
    get
    {
        return _zip;
    }
    set
    {
        _zip = value.Clamp<Int32?>(0, 99999);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

从﹋此江山别 2024-09-17 20:32:49

正如 @LBushkin Nullable< 所说T>还是T?未实现 IComparable 接口。给定的解决方案是好的,但是我更喜欢在专门的类中使用可为空的比较逻辑,遵循 单一职责原则,也可用于比较任何可空类型。

例如,您可以创建一个通用的 Nullable 类型比较器类,如下所示:

public class NullableComparer<T> : IComparer<Nullable<T>>
      where T : struct, IComparable<T>
{

     public int Compare(Nullable<T> x, Nullable<T> y)
     {
        //Compare nulls acording MSDN specification

        //Two nulls are equal
        if (!x.HasValue && !y.HasValue)
            return 0;

        //Any object is greater than null
        if (x.HasValue && !y.HasValue) 
            return 1;

        if (y.HasValue && !x.HasValue)
            return -1;

        //Otherwise compare the two values
        return x.Value.CompareTo(y.Value);
     }

}

在这种情况下,您可以像这样使用此类:

public static T? Clamp<T>(this T? value, T? min, T? max)
    where T : struct
{
    var comparer = new NullableComparer<T>();

    if (comparer.Compare(value, max) > 0)
        return max;

    if (comparer.Compare(value, min) < 0)
        return min;

    return value;
}

方便保存在帮助程序库中。

希望有帮助!

As said by @LBushkin Nullable< T > or T? does not implement IComparable interface. The given solution is ok, however I prefer to have the nullable comparing logic inside a specialized class in that matter, following the Single Responsibility Principle, and also than can be used for comparing any Nullable types.

For example, you could create a generic Nullable type comparer class like this:

public class NullableComparer<T> : IComparer<Nullable<T>>
      where T : struct, IComparable<T>
{

     public int Compare(Nullable<T> x, Nullable<T> y)
     {
        //Compare nulls acording MSDN specification

        //Two nulls are equal
        if (!x.HasValue && !y.HasValue)
            return 0;

        //Any object is greater than null
        if (x.HasValue && !y.HasValue) 
            return 1;

        if (y.HasValue && !x.HasValue)
            return -1;

        //Otherwise compare the two values
        return x.Value.CompareTo(y.Value);
     }

}

In this case you would use this class like this:

public static T? Clamp<T>(this T? value, T? min, T? max)
    where T : struct
{
    var comparer = new NullableComparer<T>();

    if (comparer.Compare(value, max) > 0)
        return max;

    if (comparer.Compare(value, min) < 0)
        return min;

    return value;
}

Handy for saving in your helpers library.

Hope it helps!

仙气飘飘 2024-09-17 20:32:49

请记住,Int32?Nullable 的简写。由于 Nullable 未实现 IComparable,因此您的结构化代码将无法编译。

但是,您可以重载该方法:

public static T? Clamp<T>(this T? value, T? min, T? max) 
    where T : struct, IComparable<T> 
{ 
    // your logic...
} 

当然,如果您计划使用可空类型,则必须定义如何限制 null 值...

如果您实际上不需要限制 null 值,那么首先在属性 getter 中检查 null 可能会更简单:

public Int32? Zip
{
   ...
   set
   {
       _zip = value == null ? value : value.Value.Clamp<Int32>(0,99999);
   }

或者更好的是,将其作为 < 的附加重载实现的一部分代码>夹紧...

Remember, Int32? is a shorthand for Nullable<Int32>. Since Nullable<T> does not implement IComparable<T>, your code, as structured, won't compile.

You can, however, overload the method:

public static T? Clamp<T>(this T? value, T? min, T? max) 
    where T : struct, IComparable<T> 
{ 
    // your logic...
} 

Of course, if you're planning on working with nullable types, you have to define how you will clamp null values...

If you don't actually need to clamp null values, it may be simpler to just first check for null in your property getter:

public Int32? Zip
{
   ...
   set
   {
       _zip = value == null ? value : value.Value.Clamp<Int32>(0,99999);
   }

Or better yet, make it part of the implementation of the additional overload to Clamp...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文