Ответ
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.
Ответ 18+ 🔞
А, ну вот опять эти два метода, которые всех путают, как близнецы-хулиганы в школе. Смотри, тут вся соль в том, что они по-разному относятся к количеству элементов в выборке, и если перепутать — получишь исключение в лицо, как хуем по лбу.
FirstOrDefault — это такой спокойный чувак: «Ну есть элементы — ок, дай первого, нет — ну и похуй, верну дефолт». Ему вообще по барабану, сколько там их в коллекции — один, сто, хоть миллион. Нашёл первого подходящего — сразу отдал и пошёл пиво пить.
А вот SingleOrDefault — это уже параноик с проверкой на уникальность. Он такой: «Слушай, если элемент есть — он должен быть ОДИН, блядь. Если их нет — ну ладно. Если их два или больше — это пиздец, нарушение контракта, я на тебя исключение кину!». И он реально пройдётся по всей коллекции до конца, чтобы убедиться, что второго такого же нет.
Вот смотри на примере, чтобы совсем понятно стало:
var numbers = new List<int> { 1, 2, 3, 2, 5 };
// FirstOrDefault — берёт первое чётное и не парится
var firstEven = numbers.FirstOrDefault(x => x % 2 == 0); // вернёт 2 и доволен
// SingleOrDefault — тут же начнёт орать, потому что чётных чисел два
var singleEven = numbers.SingleOrDefault(x => x % 2 == 0); // InvalidOperationException, ёпта!
Так когда что юзать, чтобы не обосраться?
FirstOrDefault— когда тебе просто нужен какой-нибудь подходящий элемент. Типа «найди мне любого активного пользователя». Их может быть хоть двадцать, но тебе лишь бы первого взять.SingleOrDefault— это когда ты на полном серьёзе ожидаешь либо ноль, либо ОДИН элемент. Например, «найди пользователя по его уникальному email». Если вдруг окажется два пользователя с одним email — это уже пиздец в данных, и тебе лучше узнать об этом сразу через исключение, чем потом хуй пойми где багу ловить.
Короче, SingleOrDefault — это как красная кнопка, нажимай только если уверен в уникальности. Во всех остальных случаях — FirstOrDefault, и живи спокойно.