Reputation: 22515
I have a List of objects: List<FakeObject> list = ...
Each object has a DateTime property, let's call it "Date"
I want to sort this list by this date property in descending order. However, when I try
list.Sort(new Comparison<FakeObject>((x, y) => DateTime.Compare(x.Date, y.Date)))
it complains because the Date property can be nullable.
How do I sort this list, where it treats nullable dates as MAX DATE, so it appears in the top? The quick easy alternative for me is to NOT make the Date field nullable, but let's suppose that's not an option right now.
In short: How do I sort a list of objects by DateTime, if the DateTime can be null?
Upvotes: 8
Views: 9930
Reputation: 74277
I'd do something like this.
First, given a class like this
class Widget
{
public DateTime? DateCreated { get ; set ; }
}
I'd write a custom comparer, something like this:
class Widget
{
public DateTime? DateCreated { get ; set ; }
}
class WidgetComparer : IComparer<Widget> , IComparer<DateTime?>
{
public bool NullCollatesHigh { get ; private set ; }
private WidgetComparer( bool nullCollatesHigh )
{
this.NullCollatesHigh = nullCollatesHigh ;
return ;
}
public int Compare( Widget x , Widget y )
{
int cc ;
if ( x == null && y == null ) cc = 0 ;
else if ( x != null && y != null ) cc = Compare( x.DateCreated , y.DateCreated ) ;
else if ( NullCollatesHigh ) cc = x == null ? +1 : -1 ;
else cc = x == null ? -1 : +1 ;
return cc ;
}
public int Compare(DateTime? x, DateTime? y)
{
int cc ;
if ( x == null && y == null ) cc = 0 ;
else if ( x != null && y != null ) cc = DateTime.Compare( x.Value , y.Value ) ;
else if ( NullCollatesHigh ) cc = x == null ? +1 : -1 ;
else cc = x == null ? -1 : +1 ;
return cc ;
}
}
Then it's a simple matter of
widgetList.Sort( new WidgetComparer( true/false ) ) ;
where true
specifies to collate nulls higher than anything else and false
to collate them lower than anything else.
Upvotes: 0
Reputation: 67898
One possible approach might be:
list.Sort(new Comparison<FakeObject>((x, y) =>
-DateTime.Compare(x.Date ?? DateTime.MaxValue,
y.Date ?? DateTime.MaxValue)));
UPDATE: modified to use MaxDate
after the OP edited the question for clarification.
Note that you could do this either way (MinDate
or MaxDate
). The bottom line is this, if it's null
then give it some static value that accomplishes what you want.
Upvotes: 16
Reputation: 56536
If you can replace the list, instead of modifying it in-place, you can use LINQ.
list = list.OrderByDescending(x => x.Date ?? DateTime.MaxValue).ToList();
Upvotes: 6
Reputation: 643
How about just setting the null date instances to MAX before the comparision?
list.ForEach(x => x.Date = x.Date ?? null : DateTime.Max : x.Date);
...followed by the call to your compare..
Upvotes: 0
Reputation: 203834
If you want to convert all null dates to the max date value then just do that in your function. You can use the null coalesce operator for a more succinct syntax for this:
list.Sort((x, y) =>
DateTime.Compare(x.Date ?? DateTime.MaxValue, y.Date ?? DateTime.MaxValue))
Upvotes: 8