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

«В чём разница между First и FirstOrDefault в LINQ» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

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 там, где элемент может отсутствовать, маскирует ошибки.