Вопрос по linq, .net, c# – Когда использовать .First и когда использовать .FirstOrDefault с LINQ?

749

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

When would you want to use .First? Only when you'd want to catch the exception if no results where returned?

<code>var result = List.Where(x => x == "foo").First();
</code>

And when would you want to use .FirstOrDefault? When you'd always want the default type if no result?

<code>var result = List.Where(x => x == "foo").FirstOrDefault();
</code>

And for that matter, what about Take?

<code>var result = List.Where(x => x == "foo").Take(1);
</code>
.First а также.FirstOrDefault оба принимают предикаты в качестве аргументов, поэтомуvar result = List.Where(x => x == "foo").First(); может быть переписан какvar result = List.First(x => x == "foo"); Rian Schmits
Не забудьте рассмотретьSingle а такжеSingleOrDefault, Я ненавижу, когда люди используютFirst когда они действительно имеют в видуSingle ; ) BartoszKP
Дело в том, что когда вы ожидаете одного результата, вы должны сказать об этом, а исключение указывает на сбой вашей логики. NetMage
Single или SingleOrDefault будут генерировать исключение, если возвращено более одного элемента! Я думаю, что FirstOrDefault лучше в большинстве случаев! Eric Draven
Отличная статья, которая объясняет это в полном объеме.donnfelker.com/linq-single-vs-first Latency

Ваш Ответ

12   ответов
3

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

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

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

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

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

Returns the first element of a sequence Throws exception: There are no elements in the result Use when: When more than 1 element is expected and you want only the first

FirstOrDefault:

Returns the first element of a sequence, or a default value if no element is found Throws exception: Only if the source is null Use when: When more than 1 element is expected and you want only the first. Also it is ok for the result to be empty

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

4

First()

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

FirstOrDefault()

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

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

Take это совершенно другой метод. ВозвращаетIEnumerable<T> и ни одногоT, так что нет.

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

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

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

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

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

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

739

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

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

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

@RoyiNamir, да, в контексте вопроса, где взять параметр, равный 1. Я также отметил, что в скобках сразу после этого предложения.
Take не возвращает ровно один элемент, оно возвращает не более одного элемента (если вы, конечно, укажите 1). Он также может вернуть 0 элементов, если последовательность изначально пуста.
Поцарапав это, я нашел гораздо лучший способ сделать это, используя: DefaultIfEmpty (-1) .First ()
@driis - я полагаю, что мы можем использовать мантру руководящих принципов исключительных ситуаций при выборе между First и FirstOrDefault. Спасибо за четкий ответ. Metro Smurf
Единственное, что я хотел бы добавить, - это то, что если значение по умолчанию для типа, который вы выбираете, может быть допустимым значением, например, ваш результат может быть значением int 0, то обработка исключения, кажется, лучший способ обработать это. ,
2

операторы элементов определены ниже.

First/FirstOrDefault Last/LastOrDefault Single/SingleOrDefault

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

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

First() operator returns the first element of a sequence after satisfied the condition. If no element is found then it will throw an exception.

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

FirstOrDefault() operator returns the first element of a sequence after satisfied the condition. If no element is found then it will return default value of that type.

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

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

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

Вот пример, где мы можем найти элемент с идентификатором в коллекции. Чтобы добавить больше к этому, методы First,FirstOrDefault, в идеале возвращает то же самое, когда в коллекции есть хотя бы одна запись. Если, однако, коллекция может быть пустой. затемFirst вернет исключение, ноFirstOrDefault вернусьnull или по умолчанию. Например,int вернет 0. Таким образом, использование такового хотя и считается личным предпочтением, но его лучше использоватьFirstOrDefault чтобы избежать обработки исключений. here is an example where, we run over a collection of transactionlist

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()

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

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

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

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

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

+1 за объяснение, что.FirstOrDefault вернет ноль для ссылочных типов. Я был озадачен тем, что такое «дефолт» объект будет. Этот ответ прояснил это.
@Jeroen - хорошее замечание о лучших вариантах использования Skip / Take. Metro Smurf
6

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

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

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

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

Похожие вопросы