简体   繁体   中英

C#: sort list of objects by DateTime property that is nullable

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?

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.

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

如果您可以替换列表,而不是就地修改它,则可以使用LINQ。

list = list.OrderByDescending(x => x.Date ?? DateTime.MaxValue).ToList();

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..

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM