2011-01-31 41 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);