Int32?与IComparable

10
我有一个DataGridView,其数据源是BindingList。MyObj有几个可空属性(比如int?和DateTime?)。我希望为我的绑定列表实现排序功能,这样当用户点击列标题时,DataGridView就可以对该列进行排序。
经过一番搜索和研究,我发现并遵循了这个问题的答案(DataGridView Column sorting with Business Objects)。
但是,由于Nullable类型没有实现IComparable,我无法让那个解决方案适用于它们。即使是实现了IComparable的类,如String,在其值为null时也会导致ApplySortCore(...)失败。
是否有解决方案?还是我必须为“Int32?”实现一个包装器类?
public class Int32Comparable : IComparable
{
    public int? Value { get; set; }

    #region IComparable<int?> Members

    public int CompareTo(object other)
    {
        // TODO: Implement logic here
        return -1;
    }

    #endregion
}
2个回答

11
Nullable<int>可能没有实现IComparable,但是int实现了。而且Nullable<T>总是装箱到T(例如当你将其转换为接口,如IComparable时,这是一种装箱转换)。因此,在可空属性上比较/排序不应该是一个问题。
int? value = 1;
IComparable comparable = value; // works; even implicitly

因此,顶部示例中的检查不起作用。请尝试以下内容:
Type interfaceType = prop.PropertyType.GetInterface("IComparable");
// Interface not found on the property's type. Maybe the property was nullable?
// For that to happen, it must be value type.
if (interfaceType == null && prop.PropertyType.IsValueType)
{
    Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
    // Nullable.GetUnderlyingType only returns a non-null value if the
    // supplied type was indeed a nullable type.
    if (underlyingType != null)
        interfaceType = underlyingType.GetInterface("IComparable");
}
if (interfaceType != null)
   // rest of sample

再加一点:如果你想使 null 值也能正常工作(对于字符串和可空类型),你可以尝试这个 SortCore(...) 的重新实现:

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
    IEnumerable<MyClass> query = base.Items;
    if (direction == ListSortDirection.Ascending)
        query = query.OrderBy( i => prop.GetValue(i) );
    else
        query = query.OrderByDescending( i => prop.GetValue(i) );
    int newIndex = 0;
    foreach (MyClass item in query)
    {
        this.Items[newIndex] = item;
        newIndex++;
    }
    this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}

不需要直接查找IComparable,只需让排序方法自己进行排序。


非常感谢。我还需要设置 _sortPropertyValue = prop; _sortDirectionValue = direction; _isSortedValue = true; 才能使代码正常工作。非常感谢 :) - David
关于“在可空属性上进行比较/排序不应该是一个问题”的说法,除非该属性的值为null,否则您将会得到运行时异常。(我猜的 - 我没有尝试过。) - ToolmakerSteve
@ToolmakerSteve,OrderByOrderByDescending不会在属性返回null时出现问题。它使用的默认比较器将对null值进行排序。只有当列表本身包含null条目时,您才会遇到问题。 - Ruben

4
比较可空类型时,您可以像这样做...
Int32? val1 = 30;
Int32 val2 = 50;

Int32 result = (val1 as IComparable).CompareTo(val2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接