В чём разница между First и FirstOrDefault в LINQ

Ответ

Оба метода возвращают первый элемент последовательности, но их поведение при пустой коллекции или отсутствии совпадений принципиально различается.

First()

  • Возвращает первый элемент, удовлетворяющий необязательному предикату.
  • Если результат пуст (последовательность пуста или ни один элемент не соответствует условию), метод выбрасывает InvalidOperationException.
  • Используйте, когда наличие элемента гарантировано логикой программы. Исключение в этом случае — это fail-fast механизм, указывающий на ошибку в данных или логике.

FirstOrDefault()

  • Возвращает первый элемент или значение по умолчанию для типа элемента, если последовательность пуста или нет совпадений.
    • Для ссылочных типов — null.
    • Для числовых типов значений — 0.
    • Для boolfalse.
    • Для DateTimeDateTime.MinValue.
  • Используйте, когда отсутствие элемента является нормальным, допустимым сценарием, и вы готовы обработать значение по умолчанию.

Практические примеры

var numbers = new List<int> { 1, 2, 3, 4, 5 };
var emptyList = new List<int>();

// First — когда элемент должен быть
int firstNumber = numbers.First(); // 1
int firstEven = numbers.First(n => n % 2 == 0); // 2
// int willThrow = emptyList.First(); // InvalidOperationException!

// FirstOrDefault — когда элемент может отсутствовать
int safeFirst = emptyList.FirstOrDefault(); // 0 (значение по умолчанию для int)
int firstGreaterThanTen = numbers.FirstOrDefault(n => n > 10); // 0 (нет совпадений)

// Работа со ссылочными типами
var users = new List<User>();
User foundUser = users.FirstOrDefault(u => u.Id == 123); // null
if (foundUser != null) {
    // Обрабатываем найденного пользователя
}

Рекомендация: Выбор метода — это вопрос семантики. First выражает требование, FirstOrDefault — допущение. Использование First там, где элемент может отсутствовать, маскирует ошибки.

Ответ 18+ 🔞

А, слушай, вот эта тема с First и FirstOrDefault — она вечно всех новичков в ступор вгоняет, а на деле всё проще простого, если на пальцах объяснить.

Представь себе очередь в столовую. First() — это как самый голодный мужик в начале очереди, который точно уверен, что плов сегодня есть. Он подходит к раздаче, а там — пусто. Что он делает? Правильно, он орет на всю столовую: «БЛЯДЬ, ГДЕ ЕДА?!» — это и есть твой InvalidOperationException. Используешь First(), только если ты на 146% уверен, что в коллекции что-то есть. Если нет — получишь по ебалу исключением, и правильно сделают.

А FirstOrDefault() — это я. Я подхожу по-тихому, смотрю: а плова-то и нет. Ну хуй с ним, пошел чай пить с булкой. То есть, если ничего нет, метод не орет, а просто возвращает значение по умолчанию и идет по своим делам. Для чисел это 0, для объектов — null, для boolfalse. Используешь, когда отсутствие элемента — это нормальная рабочая ситуация, а не конец света.

Вот смотри на примерах, тут всё сразу встанет на свои места:

// Допустим, у нас список
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var emptyList = new List<int>(); // А это пустой список, пиздец

// First — когда ты уверен, как в Бога
int firstNumber = numbers.First(); // 1, всё ок
int firstEven = numbers.First(n => n % 2 == 0); // 2, тоже ок
// А вот это уже пиздец:
// int willThrow = emptyList.First(); // Вылетит InvalidOperationException, потому что там нихуя нет!

// FirstOrDefault — когда похуй, найдётся — хорошо, не найдётся — иди нахуй
int safeFirst = emptyList.FirstOrDefault(); // Вернёт 0 (дефолт для int), тишина, анархия
int firstGreaterThanTen = numbers.FirstOrDefault(n => n > 10); // Тоже 0, потому что таких чисел нет

// С объектами та же история
var users = new List<User>(); // Пустой список пользователей
User foundUser = users.FirstOrDefault(u => u.Id == 123); // Вернёт null
if (foundUser != null) {
    // Ну если не null, то можно работать
    // А если null — ну значит, пользователя нет, и хуй с ним
}

Короче, суть в чём: First — это когда элемент должен быть, а его отсутствие — это пиздец и ошибка в логике. FirstOrDefault — это когда элемент может быть, а может и не быть, и тебе надо это корректно обработать. Выбирай по ситуации, а не тыкай наугад, а то потом будешь исключения ловить там, где их быть не должно, ебать.