2011-01-31 39 views
8

我想写一个通用对象比较器进行排序,但我注意到它并没有处理其中一个值比较为null的实例。当一个对象为null时,我希望它将它视为与空字符串相同。我已经尝试将空值设置为String.Empty,但随后在调用CompareTo()时出现“Object必须是String类型”的错误。如何让我的通用比较器(IComparer)处理空值?

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

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

回答

15

您无法将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); 
0

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

+0

这就是我要怎样做(后者),但我不能得到任何工作。我不知道如何声明一个新的空有效的T对象来比较而不是null。我仍然对泛型感到困惑,说实话! – NickG 2011-01-31 15:18:14

+1

@Nick,引用类型的默认`T`仍然为空。如果`T`有一个`where T:new()`约束,这将允许你在你的方法中实例化一个`T`,但是它也意味着所有'T'都可以获得一个实例化的但空的'T' `候选人必须有一个公共无参数的构造函数。在这种特殊情况下,您不应该将其作为需求,因为您应该能够有效处理代码中的空值。 – 2011-01-31 15:22:14

0
IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null) ?? ""; 
IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null) ?? ""; 

这基本上意味着,OBJ1现在将propertyInfo.GetValue(X,空),或者,如果出现这种情况为空,OBJ1将“”的值。

或者,如果问题是崩溃的GetValue对空,你可以这样做:

IComparable obj1 = ""; 
try { obj1 = (IComparable)propertyInfo.GetValue(x, null); } catch {} 
1
if (SortDirection == SortDirection.Ascending) 
    return Comparer<T>.Default.Compare(obj1, obj2); 
else 
    return Comparer<T>.Default.Compare(obj2, obj1);