Как получить последнюю дату из коллекции объектов с помощью LINQ?

У меня есть список объектов, и каждый объект имеет свойство ExpirationDate, которое имеет тип DateTime. Я хочу получить последнюю дату в списке. Есть ли элегантный способ сделать это через LINQ?

Что-то вроде:

DateTime latestDate =  myCollection.Where(r=>r.ExpirationDate.HasValue).MaxDate(r=>r.ExpirationDate.Value);

Ответ 1

DateTime? latestDate = myCollection.Max(r => r.ExpirationDate);

Intellisense должен был дать вам метод Max(). =)


Теперь, если вы должны назначить его DateTime, я бы подумал об этом:

DateTime latestDate = myCollection.Where(r => r.ExpirationDate.HasValue)
                                  .Max(r => r.ExpirationDate)
                                  .Value;

Это не будет охватывать случай пустой коллекции или коллекции с нулевыми значениями ExpirationDates.


В зависимости от вашей предыдущей логики, проверяя

myCollection.Any(r => r.ExpirationDate.HasValue)

может быть хорошей идеей, прежде чем пытаться присвоить значение.

Ответ 2

Ты почти там. Используйте Max:

DateTime? biggest = myCollection.Max(r=>r.ExpirationDate);

Если все даты истечения срока действия являются нулевыми или коллекция пуста, в результате вы получите Null, в противном случае - самую большую дату.

Как вы прокомментировали J. Sheens answer, в котором вы хотите использовать DateTime, в результате вам нужно будет что-то сделать с любой пустой коллекцией или без элементов со значением, вы можете сделать это с помощью

DateTime biggest=myCollection.Max(r=>r.ExpirationDate) ?? DateTime.MinValue

Это даст вам DateTime.MinValue вместо нулей в моем предыдущем примере (у него также есть преимущество перед использованием предложения any, который он выполняет итерацию коллекции один раз). В качестве примера я выбрал MinValue. Вы можете использовать свою собственную устаревшую дату.

Использование DateTime? лучше, потому что он позволяет вам использовать значение null для обозначения, которое оно означает: undefined, поскольку MinValue может быть допустимым элементом в вашем списке.

Ответ 3

Отсортируйте список по дате по убыванию и возьмите первый (проецируя при необходимости).

var latestExpirationDate = myCollection
    .Where(item => item.ExpirationDate.HasValue)
    .OrderByDescending(item => item.ExpirationDate)
    .Select(item => item.ExpirationDate) // DateTime?
    .FirstOrDefault();
if (latestExpirationDate != null)
{
    // do something with the value stored in latestExpirationDate
}

Как я написал это, у меня создалось впечатление, что метод Max() работает только с числовыми типами (т.е. int, short, decimal и т.д.). Он также работает с объектами DateTime. Так что это может сработать:

var expiredItems = myCollection
    .Where(item => item.ExpirationDate.HasValue);
if (expiredItems.Any())
{
    var latestExpirationDate = expiredItems.Max(item => item.ExpirationDate.Value);
    // do something with latestExpirationDate
}

Ответ 4

Просто проверьте, нет ли проверки NullReference перед назначением .ExpriationDate:

DateTime maxDate = myCollection.OrderByDescending(o => o.ExpirationDate).Take(1).FirstOrDefault().ExpirationDate;

У Бобал была правильная идея с

DateTime maxDate = objL.Max(o => o.ExpirationDate);