Когда использовать .First и когда использовать .FirstOrDefault с LINQ?

605

Я обыскал и на самом деле не нашел четкого ответа о том, когда вы хотите использовать .First, и когда вы хотите использовать .FirstOrDefault с LINQ.

  • Когда вы хотите использовать .First? Только когда вы хотите поймать исключение, если не возвращены результаты?

    var result = List.Where(x => x == "foo").First();
    
  • И когда вы хотите использовать .FirstOrDefault? Когда вы всегда хотите тип по умолчанию, если нет результата?

    var result = List.Where(x => x == "foo").FirstOrDefault();
    
  • И в этом отношении, как насчет Take?

    var result = List.Where(x => x == "foo").Take(1);
    
  • 81
    .First и .FirstOrDefault оба принимают в качестве аргументов предикат, поэтому var result = List.Where(x => x == "foo").First(); может быть переписано как var result = List.First(x => x == "foo");
  • 50
    Не забудьте рассмотреть Single и SingleOrDefault . Я ненавижу, когда люди используют First когда они действительно имеют в виду Single ; )
Показать ещё 4 комментария
Теги:
linq

14 ответов

616
Лучший ответ

Я бы использовал First(), когда я знаю или ожидаю, что в последовательности будет хотя бы один элемент. Другими словами, когда это исключительное происхождение, последовательность пуста.

Используйте FirstOrDefault(), когда вы знаете, что вам нужно будет проверить, есть ли элемент или нет. Другими словами, когда законно, чтобы последовательность была пустой. Вы не должны полагаться на обработку исключений для проверки. (Это плохая практика и может повредить производительность).

Наконец, разница между First() и Take() заключается в том, что First() возвращает сам элемент, а Take() возвращает последовательность элементов, содержащую ровно один элемент. (Если вы передаете 1 в качестве параметра).

  • 4
    @driis - я полагаю, что мы можем использовать мантру руководящих принципов исключительных ситуаций при выборе между First и FirstOrDefault. Спасибо за четкий ответ.
  • 4
    Единственное, что я хотел бы добавить, - это то, что если значение по умолчанию для выбранного вами типа может быть допустимым значением, например, ваш результат может быть значением int 0, то обработка исключения, кажется, лучший способ справиться с этим. ,
Показать ещё 9 комментариев
215

.First выдаст исключение, если результатов нет. .FirstOrDefault не будет, он просто вернет либо нулевой (ссылочные типы), либо значение по умолчанию для типа значения. (например, например, 0 для int.) Вопрос здесь не в том, когда вы хотите использовать тип по умолчанию, но больше: готовы ли вы обрабатывать исключение или обрабатывать значение по умолчанию? Поскольку исключения должны быть исключительными, FirstOrDefault является предпочтительным, если вы не уверены, собираетесь ли вы получить результаты из своего запроса. Когда логически должны быть данные, обработка исключений может быть рассмотрена.

Skip() и Take() обычно используются при настройке поискового вызова в результатах. (Как показано первые 10 результатов, а следующие 10 на следующей странице и т.д.)

Надеюсь, это поможет.

  • 5
    @Jeroen - хорошее замечание о лучших вариантах использования Skip / Take.
  • 3
    +1 для объяснения того, что .FirstOrDefault вернет null для ссылочных типов. Я был озадачен тем, каким будет объект «по умолчанию». Этот ответ прояснил это.
86

.First() выдает исключение, если нет строки, которую нужно вернуть, тогда как .FirstOrDefault() вернет значение по умолчанию (NULL для всех типов ссылок).

Итак, если вы готовы и готовы обработать возможное исключение, .First() в порядке. Если вы предпочитаете проверять возвращаемое значение для!= Null в любом случае, тогда .FirstOrDefault() - ваш лучший выбор.

Но я предполагаю, что это тоже личное предпочтение. Используйте то, что имеет больше смысла для вас и лучше подходит для вашего стиля кодирования.

54

Первый()

  • Возвращает первый элемент последовательности.
  • Он выдает ошибку, когда в результате нет элемента или источник имеет значение null.
  • вы должны использовать его, если ожидается более одного элемента, и вы хотите только первый элемент.

FirstOrDefault()

  • Возвращает первый элемент последовательности или значение по умолчанию, если элемент не найден.
  • Он выдает ошибку Только в том случае, если источник имеет значение null.
  • вы должны использовать его, если ожидается более одного элемента, и вам нужен только первый элемент. Также хорошо, если результат пуст.

У нас есть таблица UserInfos, в которой есть некоторые записи, как показано ниже. На основе приведенной ниже таблицы я создал пример...

Изображение 1017

Как использовать First()

var result = dc.UserInfos.First(x => x.ID == 1);

Существует только одна запись, где ID == 1. Должен вернуть эту запись
ID: 1 Имя: Manish Фамилия: Dubey Электронная почта: [email protected]

var result = dc.UserInfos.First(x => x.FName == "Rahul");   

Есть несколько записей, где FName == "Rahul". Первая запись должна быть возвращена.
ID: 7 Имя: Rahul Фамилия: Sharma Электронная почта: [email protected]

var result = dc.UserInfos.First(x => x.ID ==13);

Нет записи с идентификатором == 13. Должна быть ошибка.
InvalidOperationException: Последовательность не содержит элементов

Как использовать FirstOrDefault()

var result = dc.UserInfos.FirstOrDefault(x => x.ID == 1);

Существует только одна запись, где ID == 1. Должен вернуть эту запись
ID: 1 Имя: Manish Фамилия: Dubey Электронная почта: [email protected]

var result = dc.UserInfos.FirstOrDefault(x => x.FName == "Rahul");

Есть несколько записей, где FName == "Rahul". Первая запись должна быть возвращена.
ID: 7 Имя: Rahul Фамилия: Sharma Электронная почта: [email protected]

var result = dc.UserInfos.FirstOrDefault(x => x.ID ==13);

Нет записи с идентификатором == 13. Возвращаемое значение равно null

Надеюсь, это поможет вам понять, когда использовать First() или FirstOrDefault().

  • 4
    На мой взгляд, утверждение «ошибка должна произойти». под третьим FirstOrDefault () - пример вводит в заблуждение.
  • 0
    Здравствуйте, вы хорошо объясните, но я немного запутался, когда происходит получение данных из соединения, и когда идентификатор не существовал в таблице внешних ключей в то время, какой из них используется? В настоящее время я использую First (), но после прочтения вашего ответа я понятия не имею. Пожалуйста, помогите
17

Прежде всего, Take - совершенно другой метод. Он возвращает IEnumerable<T>, а не один T, так что выходим.

Между First и FirstOrDefault вы должны использовать First, когда вы уверены, что элемент существует, а если нет, то есть ошибка.

Кстати, если ваша последовательность содержит default(T) элементов (например, null), и вам нужно различать пустое, а первый элемент - null, вы не можете использовать FirstOrDefault.

  • 2
    @Mehrdad - замечательные моменты, re: .First возвращает IEnumerable и когда не следует использовать FirstOrDefault.
13

Во-первых:

  • Возвращает первый элемент последовательности
  • Выдает исключение: в результате нет элементов
  • Использовать когда: Когда ожидается более 1 элемента, и вы хотите только первый

FirstOrDefault:

  • Возвращает первый элемент последовательности или значение по умолчанию, если элемент не найден
  • Выдает исключение: только если источник имеет значение null
  • Использовать когда: Когда ожидается более 1 элемента, и вы хотите только первый. Также нормально, чтобы результат был пустым.

От: http://www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/

6

Еще одно отличие заключается в том, что если вы отлаживаете приложение в производственной среде, у вас может не быть доступа к номерам строк, поэтому определение того, какой конкретный оператор .First() в методе генерирует исключение, может быть затруднительным.

Сообщение об исключении также не будет содержать никаких выражений Lambda, которые вы могли бы использовать, что затрудняет отладку любой проблемы.

Вот почему я всегда использую FirstOrDefault(), хотя я знаю, что нулевая запись будет представлять исключительную ситуацию.

var customer = context.Customers.FirstOrDefault(i => i.Id == customerId);
if (customer == null)
{
   throw new Exception(string.Format("Can't find customer {0}.", customerId));
}
3

Я нашел веб-сайт, в котором apperars объясняет необходимость FirstOrDefault http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
Если результатов нет, и вы хотите вызвать First() или Single(), чтобы получить одну строку... Вы получите исключение "Последовательность не содержит элементов".

Отказ от ответственности: я никогда не использовал LINQ, поэтому извиняюсь, если это не соответствует значению.

  • 2
    Ссылка больше не работает, хотя.
2

Первый()

Когда вы знаете, что результат содержит более 1 элемента, и вы должны использовать только первый элемент последовательности.

FirstOrDefault()

FirstOrDefault() аналогичен First(), за исключением того, что если ни один элемент не соответствует указанному условию, чем возвращает значение по умолчанию для базового типа общей коллекции. Он не бросает InvalidOperationException, если элемент не найден. Но коллекция элемента или последовательности имеет значение null, чем исключение.

  • 0
    Здравствуйте, вы хорошо объясните, но я немного запутался, когда происходит получение данных из соединения, и когда идентификатор не существовал в таблице внешних ключей в то время, какой из них используется? В настоящее время я использую First (), но после прочтения вашего ответа я понятия не имею. Пожалуйста, помогите
2
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

Какой из них использовать? Это должно решаться бизнес-логикой, а не страх перед сбоем исключений/программ.

Например, Если бизнес-логика говорит, что мы не можем иметь нулевые транзакции в любой рабочий день (просто предположим). Тогда вы не должны пытаться справиться с этим сценарием с помощью некоторых интеллектуальных программ. Я всегда буду использовать First() над такой коллекцией, и пусть программа потерпит неудачу, если что-то еще испортит бизнес-логику.

код:

var transactionsOnWorkingDay = GetTransactionOnLatestWorkingDay();
var justNeedOneToProcess = transactionsOnWorkingDay.First(): //Not FirstOrDefault()

Я хотел бы видеть другие комментарии по этому поводу.

  • 0
    Значением по умолчанию для ссылочного и обнуляемого типов является null.
  • 0
    Быстро завершиться неудачей - это хорошо, однако для описанного вами сценария я предпочел бы сначала увидеть, не удалось ли это, поймать исключение и затем вернуть значимую ошибку. Как catch (InvalidOperationException e) {throw new InvalidOperationException ("Не может иметь ноль транзакций за день!", E)}; Но да, использование по умолчанию, чтобы избежать реальной проблемы бизнес-логики, очень плохо.
1

Хорошо, позвольте мне дать мои два цента. First/Firstordefault предназначены для использования второго конструктора. Я не буду объяснять, что это такое, но это когда вы потенциально всегда будете использовать его, потому что вы не хотите вызывать исключение.

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));
  • 0
    Не совсем. Первый конструктор широко используется, когда вам нужно извлечь только один элемент или избежать ошибки компиляции при присваивании результата значению, которое не является массивом, и вы уверены, что запрос возвращает ровно один результат. Хотя использование второго конструктора может показаться быстрее, чем использование дополнительного .Where () (поскольку вы думаете, что LINQ прекращает оценку элементов в списке после нахождения первого), он всегда останавливается на первом элементе
0

Этот тип функции принадлежит операторам элементов. Некоторые полезные операторы элемента определены ниже.

  • Первый /FirstOrDefault
  • Последняя /LastOrDefault
  • Single/SingleOrDefault

Мы используем операторы элементов, когда нам нужно выбрать один элемент из последовательности, основанный на определенном условии. Вот пример.

  List<int> items = new List<int>() { 8, 5, 2, 4, 2, 6, 9,2,10};

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

int result = items.Where(item = > item == 2).First();

Оператор FirstOrDefault() возвращает первый элемент последовательности после выполнения условия. Если ни один элемент не найден, он вернет значение по умолчанию этого типа.

int result1 = items.Where(item = > item == 2).FirstOrDefault();

  • 0
    хорошо объяснено на простом для понимания примере.
-3
-8

linq много способов реализовать один простой запрос в коллекциях, просто мы записываем объединения в sql, фильтр может применяться первым или последним в зависимости от необходимости и необходимости.

Вот пример, где мы можем найти элемент с идентификатором в коллекции. Чтобы добавить больше об этом, методы First, FirstOrDefault, в идеале будут возвращены, если коллекция имеет хотя бы одну запись. Если, однако, коллекция в порядке, чтобы быть пустым. то First вернет исключение, но FirstOrDefault вернет null или значение по умолчанию. Например, int вернет 0. Таким образом, использование такого, хотя и считается личным предпочтением, но лучше использовать FirstOrDefault, чтобы избежать обработки исключений. Изображение 1018

Ещё вопросы

Сообщество Overcoder
Наверх
Меню