Ответ
FirstOrDefault и SingleOrDefault — методы расширения LINQ с разной семантикой гарантий относительно количества элементов в результирующей последовательности.
| Критерий | FirstOrDefault |
SingleOrDefault |
|---|---|---|
| Ожидаемое количество | 0 или более (берётся первый) | Строго 0 или 1 |
| Поведение при 0 элементов | Возвращает default(T) (например, null) |
Возвращает default(T) |
| Поведение при 2+ элементах | Возвращает первый элемент | Выбрасывает InvalidOperationException |
| Производительность | Завершается при нахождении первого элемента | Всегда проверяет всю последовательность на наличие второго элемента |
Примеры:
// Коллекция с дубликатами
var numbers = new List<int> { 1, 2, 3, 2, 5 };
var firstEven = numbers.FirstOrDefault(x => x % 2 == 0); // 2 (первое чётное)
// Это сработает, хотя чётных чисел несколько.
var singleEven = numbers.SingleOrDefault(x => x % 2 == 0); // InvalidOperationException!
// Исключение, потому что чётных чисел больше одного.
// Корректное использование SingleOrDefault — когда элемент должен быть уникальным
var singleOne = numbers.SingleOrDefault(x => x == 1); // 1 (единственный)
var singleTen = numbers.SingleOrDefault(x => x == 10); // 0 (не найдено)
Когда что использовать:
FirstOrDefault— когда вам нужен любой подходящий элемент (например, «найти активного пользователя» — их может быть несколько, но берём первого).SingleOrDefault— когда вы ожидаете строго один или ноль элементов, и наличие дубликатов является ошибкой данных (например, «найти пользователя по уникальному email»).
Совет: Использование SingleOrDefault — это явное утверждение об уникальности. Если есть сомнения, используйте FirstOrDefault.