【问题标题】:Nullable generic type used with IComparable. Is it possible?与 IComparable 一起使用的可空泛型类型。是否可以?
【发布时间】:2010-07-20 21:37:15
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# generics nullable icomparable


    【解决方案1】:

    正如@LBushkin Nullable 或T 所说的那样?不实现 IComparable 接口。给定的解决方案是可以的,但是我更喜欢在一个专门的类中使用可空比较逻辑,在 Single Responsibility Principle 之后,也可以用于比较任何可空类型。

    例如,您可以像这样创建一个通用的 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;
    }
    

    方便保存在您的助手库中。

    希望对你有帮助!

    【讨论】:

      【解决方案2】:

      请记住,Int32? 是 Nullable&lt;Int32&gt; 的简写。由于Nullable&lt;T&gt; 没有实现IComparable&lt;T&gt;,因此您的代码按结构化方式将无法编译。

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

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

      或者更好的是,让它成为Clamp的额外重载实现的一部分...

      【讨论】:

      • 我不知道我为什么不这样做 (value == null ) ?值:value.Clamp(0, 99999);首先。我想我只是想强迫 Clamp 自动完成。但是,是的,实际上不将其归零更有意义,因为它正在夹紧。
      猜你喜欢
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 1970-01-01
      相关资源
      最近更新 更多