【问题标题】:How can I make my generic comparer (IComparer) handle nulls?如何让我的通用比较器 (IComparer) 处理空值?
【发布时间】:2011-06-18 15:43:31
【问题描述】:

我正在尝试编写一个用于排序的通用对象比较器,但我注意到它不处理它所比较的​​值之一为空的实例。当一个对象为空时,我希望它像空字符串一样对待它。我尝试将 null 值设置为 String.Empty,但是在调用 CompareTo() 时出现“对象必须是字符串类型”的错误。

public int Compare(T x, T y)
{
    PropertyInfo propertyInfo = typeof(T).GetProperty(sortExpression);
    IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
    IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);

    if (obj1 == null) obj1 = String.Empty; // This doesn't work!
    if (obj2 == null) obj2 = String.Empty; // This doesn't work!

    if (SortDirection == SortDirection.Ascending)
        return obj1.CompareTo(obj2);
    else
        return obj2.CompareTo(obj1);
}

我现在很坚持!任何帮助将不胜感激。

【问题讨论】:

    标签: c# .net sorting icomparer


    【解决方案1】:

    您不能将 T 视为空字符串,除非您的 T 被有效地限制为字符串。你应该做的是有一个比较空值的计划。比如

    if (obj1 == null && obj2 == null)
       return 0;
    else if (obj1 == null)
       return -1;
    else if (obj2 == null)
       return 1;
    else 
       return obj1.CompareTo(obj2);
    

    【讨论】:

    • 谢谢安东尼,这很管用!我真的不知道为什么我似乎从来没有发现简单的解决方案......
    【解决方案2】:
    if (SortDirection == SortDirection.Ascending)
        return Comparer<T>.Default.Compare(obj1, obj2);
    else
        return Comparer<T>.Default.Compare(obj2, obj1);
    

    【讨论】:

      【解决方案3】:

      由于T 是泛型类型,您不能为其分配String 值;您只能为其分配一个T 类型的值。如果您只打算使用它来比较字符串,请使用String 而不是T。否则,添加空检查并决定null 应该落在哪里。

      【讨论】:

      • 这就是我想要做的(后者),但我就是什么都做不了。我不知道如何声明一个新的空有效 T 对象来比较它而不是 null。老实说,我仍然对泛型感到困惑!
      • @Nick,引用类型的默认T 仍然为空。如果T 有一个where T : new() 约束,则可以获得一个已实例化但为空的T,这将允许您在您的方法中实例化一个T,但这也意味着所有T 候选人都必须有一个公共的无参数构造函数。在这种特殊情况下,您不应将此作为要求,因为您应该能够有效地处理代码中的空值。
      【解决方案4】:
      IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null) ?? "";
      IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null) ?? "";
      

      这基本上意味着 obj1 现在将是 propertyInfo.GetValue(x, null) 的值,或者,如果碰巧为 null,则 obj1 将是 ""。

      或者,如果问题是 GetValue 在 null 上崩溃,您可以执行以下操作:

      IComparable obj1 = "";
      try { obj1 = (IComparable)propertyInfo.GetValue(x, null); } catch {}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-20
        • 1970-01-01
        • 1970-01-01
        • 2016-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多