2011-01-31 22 views
8

Tôi đang cố viết một trình so sánh đối tượng chung để sắp xếp, nhưng tôi đã nhận thấy nó không xử lý cá thể trong đó một trong các giá trị mà nó so sánh là rỗng. Khi một đối tượng là null, tôi muốn nó xử lý nó giống như chuỗi rỗng. Tôi đã thử thiết lập các giá trị null cho String.Empty nhưng sau đó tôi nhận được một lỗi của "Object phải được loại String" khi gọi CompareTo() trên đó.Làm cách nào để tôi có thể làm cho trình so sánh chung (IComparer) xử lý các giá trị rỗng?

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

Tôi khá mắc kẹt với điều này ngay bây giờ! Bất kỳ trợ giúp sẽ được đánh giá cao.

Trả lời

15

Bạn không thể đối xử với T bạn như là một chuỗi rỗng trừ T của bạn đã có hiệu quả hạn chế để trở thành một chuỗi. Những gì bạn nên làm là có kế hoạch so sánh số không. Chẳng hạn như

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

Cảm ơn Anthony, điều đó có tác dụng! Tôi không thực sự biết tại sao tôi không bao giờ có vẻ phát hiện ra giải pháp đơn giản ... – NickG

0

T là loại chung, bạn không thể chỉ định giá trị String; bạn chỉ có thể chỉ định giá trị loại T. Nếu bạn chỉ sử dụng điều này để so sánh các chuỗi, hãy sử dụng String thay vì T. Nếu không, hãy thêm kiểm tra null và quyết định vị trí theo thứ tự null sẽ giảm.

+0

Đó là những gì tôi đang cố gắng thực hiện (sau này) nhưng tôi chỉ không thể có được bất cứ điều gì để làm việc. Tôi không biết cách khai báo một đối tượng T hợp lệ rỗng mới để nó so sánh với thay vì null. Tôi vẫn còn bối rối bởi generics phải trung thực! – NickG

+1

@Nick, một 'T' mặc định cho loại tham chiếu sẽ vẫn là rỗng. Một 'T' được khởi tạo nhưng có thể lấy ra nếu' T' có một ràng buộc 'where T: new()', cho phép bạn tạo một 'T' bên trong phương thức của bạn, nhưng nó cũng có nghĩa là tất cả' T 'ứng viên sẽ phải có một hàm tạo tham số công khai. Trong tình huống cụ thể này, bạn không nên thực hiện yêu cầu này vì bạn có thể xử lý hiệu quả với các giá trị rỗng trong mã của bạn. –

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

này về cơ bản có nghĩa là giờ đây obj1 sẽ là giá trị của propertyInfo.GetValue (x, null) hoặc, nếu điều đó xảy ra để được null, obj1 sẽ là "".

Hoặc nếu vấn đề là các GetValue treo trên null bạn có thể làm một cái gì đó như:

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); 
Các vấn đề liên quan