Максимальное возвращаемое значение, если пустой запрос

У меня есть этот запрос:

int maxShoeSize=Workers.Where(x=>x.CompanyId==8).Max(x=>x.ShoeSize);

Что будет в maxShoeSize, если в компании 8 нет рабочих?

UPDATE:
Как я могу изменить запрос, чтобы получить 0, а не исключение?

Ответ 1

int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                         .Select(x => x.ShoeSize)
                         .DefaultIfEmpty(0)
                         .Max();

Нуль в DefaultIfEmpty не нужен.

Ответ 2

Я знаю, что это старый вопрос, и принятый ответ работает, но этот вопрос ответил на мой вопрос о том, приведет ли такой пустой набор к исключению или к результату default(int).

Однако принятый ответ, хотя он и работает, не является идеальным решением IMHO, которое здесь не приводится. Таким образом, я предоставляю его в своем собственном ответе на благо любого, кто его ищет.

Оригинальный код OP:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize);

Вот как я писал бы это для предотвращения исключений и предоставления результата по умолчанию:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize as int?) ?? 0;

Это приводит к тому, что тип возврата функции Max будет int?, что позволяет получить результат null, а затем ?? заменяет результат null на 0.

Ответ 3

Max() в этом случае ничего не вернет.

Он поднимет InvalidOperationException, поскольку источник не содержит элементов.

Ответ 4

int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                     .Select(x => x.ShoeSize)
                     .DefaultIfEmpty()
                     .Max();

Ответ 5

Макс будет бросать System.InvalidOperationException "Последовательность не содержит элементов"

class Program
{
    static void Main(string[] args)
    {
        List<MyClass> list = new List<MyClass>();

        list.Add(new MyClass() { Value = 2 });

        IEnumerable<MyClass> iterator = list.Where(x => x.Value == 3); // empty iterator.

        int max = iterator.Max(x => x.Value); // throws System.InvalidOperationException
    }
}

class MyClass
{
    public int Value;
}

Ответ 6

int maxShoeSize=Workers.Where(x=>x.CompanyId==8)
    .Max(x=>(int?)x.ShoeSize).GetValueOrDefault();

(предполагая, что ShoeSize имеет тип int)

Если Workers является DbSet или ObjectSet из Entity Framework, ваш первоначальный запрос будет вызывать InvalidOperationException, но не жалуется на пустую последовательность, но жалуется, что материализованное значение NULL не может быть преобразовано в int.

Ответ 7

NB: запрос с DefaultIfEmpty() может быть значительно медленнее. В моем случае это был простой запрос с .DefaultIfEmpty(DateTime.Now.Date).

Я был слишком ленив к профилю. Но, очевидно, EF попытался получить все строки, а затем взять значение Max().

Вывод: иногда обработка InvalidOperationException может быть лучшим выбором.

Ответ 8

Для обработки предиката вы можете использовать тернар внутри .Max(),

// assumes Workers != null && Workers.Count() > 0
int maxShoeSize = Workers.Max(x => (x.CompanyId == 8) ? x.ShoeSize : 0);

Вам нужно будет обрабатывать коллекцию Workers, являющуюся нулевой/пустой, если это возможно, но это будет зависеть от вашей реализации.

Ответ 9

Вы можете попробовать следующее:

int maxShoeSize = Workers.Where(x=>x.CompanyId == 8).Max(x => x.ShoeSize) ?? 0;

Ответ 10

Вы можете проверить, есть ли какие-либо работники перед выполнением Max().

private int FindMaxShoeSize(IList<MyClass> workers) {
   var workersInCompany = workers.Where(x => x.CompanyId == 8);
   if(!workersInCompany.Any()) { return 0; }
   return workersInCompany.Max(x => x.ShoeSize);
}

Ответ 11

Если это Linq to SQL, я не люблю использовать Any(), потому что это приводит к нескольким запросам SQL-сервера.

Если ShoeSize не является полем с нулевым значением, то использование только .Max(..) ?? 0 не будет работать, но следующее:

int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0;

Он абсолютно не меняет испускаемый SQL, но возвращает 0, если последовательность пуста, потому что она меняет Max(), чтобы вернуть int? вместо int.