Коли використовувати. Спочатку і коли використовувати .FirstOrDefault з LINQ?


824

Я шукав навколо, і насправді не знайшов чіткої відповіді, коли ви хочете використовувати .Firstта коли ви хочете використовувати .FirstOrDefaultLINQ.

  • Коли ви хочете використовувати .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);

86
.Firstі .FirstOrDefaultобидва приймають предикати як аргументи, тому var result = List.Where(x => x == "foo").First();можна було б переписати якvar result = List.First(x => x == "foo");
Rian Schmits

59
Не забудьте врахувати Singleі SingleOrDefault. Я ненавиджу, коли люди використовують, Firstколи вони справді мають на увазі Single; )
BartoszKP

19
Single або SingleOrDefault буде кидати виняток, якщо повернуто більше одного елемента! Я думаю, що FirstOrDefault краще в більшості випадків!
Ерік Дравен

21
Справа в тому, коли ви очікуєте єдиного результату, ви повинні так сказати, а виняток вказує на те, що ваша логіка не вдалася.
NetMage

1
Також врахуйте, що використання .FirstOrDefault()завжди дає можливість кинути більш значущий виняток. Якщо виняток послідовності викинуто .First()в методі більше, ніж один , може бути важко розрізнити, яке твердження є проблемою.
StingyJack

Відповіді:


807

Я б використовував, First()коли знаю або очікую, що послідовність матиме хоча б один елемент. Іншими словами, коли винятковий випадок, послідовність порожня.

Використовуйте, FirstOrDefault()коли знаєте, що вам потрібно буде перевірити, був елемент чи ні. Іншими словами, коли законно, щоб послідовність була порожньою. Ви не повинні покладатися на обробку виключень для перевірки. (Це погана практика і може зашкодити роботі).

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


4
@driis - Я б міг уявити, що ми можемо використовувати мантру принципу виключного винятку, коли обираємо між First та FirstOrDefault. Дякую за чітку відповідь.
Метро Смурф

5
Єдине, що я хочу додати, - це те, що якщо типовим значенням для типу, який ви обираєте, може бути дійсне значення, наприклад, результатом може бути значення int 0, то обробка виключення, здається, є найкращим способом впоратися з цим. .
PeterBelm

25
Помініть це, я знайшов набагато приємніший спосіб досягти цього, використовуйте: DefaultIfEmpty (-1). Перший ()
PeterBelm

5
Take не повертає рівно один елемент, він повертає максимум один елемент (якщо вказати 1, звичайно). Він може також повернути 0 елементів, якщо послідовність спочатку порожня.
SPIRiT_1984

3
@RoyiNamir, так у контексті запитання, де параметр потрібно взяти 1. Я також зазначив, що в паронах одразу після цього речення.
дріс

272

.Firstвикине виняток, коли результатів немає. .FirstOrDefaultне буде, він просто поверне або null (типи посилань), або значення за замовчуванням типу значення. (Наприклад , як 0для внутр.) Питання тут не тоді , коли ви хочете , тип за замовчуванням, але більше: Ви готові обробляти виключення або обробляти значення за замовчуванням? Оскільки винятки мають бути винятковими, FirstOrDefaultбажано, коли ви не впевнені, чи збираєтеся ви отримувати результати зі свого запиту. Якщо логічно дані мають бути, може бути розглянута обробка виключень.

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

Сподіваюсь, це допомагає.


5
@Jeroen - хороший момент щодо кращих випадків використання пропуску / прийому.
Метро Смурф

4
+1 для пояснення, яке .FirstOrDefaultповерне нульове значення для еталонних типів. Мене збентежило те, що буде об’єктом "за замовчуванням". Ця відповідь це очистила.
Майк Таверн

115

.First()викине виняток, якщо немає рядка для повернення, а .FirstOrDefault()поверне значення за замовчуванням ( NULLдля всіх типів посилань).

Тож якщо ви готові і готові впоратися з можливим винятком, .First()це добре. Якщо ви віддаєте перевагу перевірити значення повернення для != nullбудь-якого випадку, тоді .FirstOrDefault()ваш кращий вибір.

Але я гадаю, це теж трохи особисті переваги. Використовуйте те, що має більше сенсу для вас і краще відповідає вашому стилю кодування.


66

Спочатку()

  1. Повертає перший елемент послідовності.
  2. Він видає помилку, коли в результаті немає жодного елемента, або джерело є нульовим.
  3. ви повинні використовувати його, якщо очікується більше одного елемента, і ви хочете лише перший елемент.

FirstOrDefault ()

  1. Повертає перший елемент послідовності або значення за замовчуванням, якщо не знайдено жодного елемента.
  2. Він видає помилку, лише якщо джерело є нульовим.
  3. ви повинні використовувати його, якщо очікується більше одного елемента, і ви хочете лише перший елемент. Також добре, якщо результат порожній.

У нас є таблиця UserInfos, в якій є деякі записи, як показано нижче. На основі цієї таблиці нижче я створив приклад ...

Таблиця UserInfo

Як користуватися першим ()

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

Є лише один запис, де ID == 1. Слід повернути цей запис
ID: 1 Ім'я: Прізвище Маніш: Дюбі Електронна пошта: xyz@xyz.com

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

Існує кілька записів, де FName == "Рахул". Першим записом має бути повернення.
ID: 7 Ім'я: Рахул Прізвище: Шарма Email: xyz1@xyz.com

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 Ім'я: Прізвище Маніш: Дюбі Електронна пошта: xyz@xyz.com

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

Існує кілька записів, де FName == "Рахул". Першим записом має бути повернення.
ID: 7 Ім'я: Рахул Прізвище: Шарма Email: xyz1@xyz.com

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

Немає запису з ідентифікатором == 13. Повернене значення є нульовим

Сподіваємось, це допоможе вам зрозуміти, коли використовувати First()або FirstOrDefault().


4
На мою думку, твердження «Помилка повинна статися». під третім FirstOrDefault () - приклад вводить в оману.
Jannik

Здравствуйте, ви добре поясните, але я трохи розгублений, коли отримують дані про приєднання та коли ідентифікатор не існував у таблиці іноземних ключів на той час, який з них використовується? Наразі я використовую First (), але після прочитання вашої відповіді я поняття не маю. Будь ласка, допоможіть
Brijesh Mavani

20

Перш за все, Takeце зовсім інший метод. Він повертає IEnumerable<T>і не єдине T, так що це не вдається .

Між Firstі FirstOrDefault, ви повинні використовувати, Firstколи ви впевнені, що елемент існує, а якщо його немає, то виникає помилка.

До речі, якщо ваша послідовність містить default(T)елементи (наприклад null), і вам потрібно розрізняти порожній і перший, який є null, ви не можете використовувати FirstOrDefault.


2
@Mehrdad - чудові моменти, повторно:. Перший повертає IEnumerable та коли не використовувати FirstOrDefault.
Метро Смурф

15

Спочатку:

  • Повертає перший елемент послідовності
  • Виняток викидає: в результаті немає елементів
  • Використовуйте, коли: Коли очікується більше 1 елемента, і ви хочете лише перший

FirstOrDefault:

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

Від: http://www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/


10

Ще одна відмінність, яку слід зазначити, що якщо ви налагоджуєте програму у виробничому середовищі, у вас може не бути доступу до номерів рядків, щоб визначити, який саме .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));
}

5

Спочатку()

Коли ви знаєте, що результат містить більше 1 очікуваного елемента, і вам слід лише перший елемент послідовності.

FirstOrDefault ()

FirstOrDefault () подібно до First (), за винятком того, що якщо жоден елемент не відповідає заданій умові, ніж він повертає значення за замовчуванням базового типу загальної колекції. Він не кидає InvalidOperationException, якщо не знайдено жодного елемента. Але колекція елемента або послідовності є нульовою, ніж вона викидає виняток.


Здравствуйте, ви добре поясните, але я трохи розгублений, коли отримують дані про приєднання та коли ідентифікатор не існував у таблиці іноземних ключів на той час, який з них використовується? Наразі я використовую First (), але після прочитання вашої відповіді я поняття не маю. Будь ласка, допоможіть
Brijesh Mavani

4

Цей тип функції належить до операторів елементів. Деякі оператори корисних елементів визначені нижче.

  1. Перший / FirstOrDefault
  2. Last / LastOrDefault
  3. Single / SingleOrDefault

Ми використовуємо оператори елементів, коли нам потрібно вибрати один елемент із послідовності на основі певної умови. Ось приклад.

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

Перший () оператор повертає перший елемент послідовності після виконання умови. Якщо жодного елемента не буде знайдено, він викине виняток.

int result = items.Where (предмет => предмет == 2). Перший ();

Оператор FirstOrDefault () повертає перший елемент послідовності після виконання умови. Якщо жодного елемента не знайдено, він поверне значення за замовчуванням цього типу.

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


чудово пояснено з легким для розуміння прикладом.
Арслан Бхатті

3

Я знайшов веб-сайт, на якому заявники пояснюють необхідність http://OpDefault
http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
Якщо запиту немає результатів, і ви хочете зателефонувати спочатку () або Single (), щоб отримати один рядок ... Ви отримаєте виняток "Послідовність не містить елементів".

Відмова: Я ніколи не використовував LINQ, тож вибачте, якщо це далеко від позначки.


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

Я хотів би бачити інші коментарі щодо цього.


Значення за замовчуванням для еталонних та мінливих типів є нульовим.
дса

Невдача швидко - це добре, однак для описаного вами сценарію я скоріше побачу спочатку, чи не вдасться це зробити, вилучити виняток, а потім повернути істотну помилку. Як улов (InvalidOperationException e) {киньте новий InvalidOperationException ("Не можна робити нульові транзакції за день!", Е)}; Але так, використання за замовчуванням, щоб уникнути роботи з реальною проблемою бізнес-логіки, дуже погано.
Матьєсон

1

Гаразд, дай мені два центи. Перший / Firstordefault - це коли використовується другий конструктор. Я не поясню, що це таке, але це потенційно завжди, якщо ви не хочете викликати виняток.

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));

Не зовсім. Перший конструктор широко використовується, коли потрібно отримати лише один елемент або уникнути помилки компіляції при призначенні результату значення, яке не є масивом, і ви впевнені, що запит повертає саме один результат. Хоча може використовуватись другий конструктор швидше, ніж використовувати додатковий. Де () (оскільки ви думаєте, що LINQ припиняє оцінювати елементи в списку після знаходження першого), він завжди зупиняється на першому елементі
usr-local-ΕΨΗΕΛΩΝ

0

Інші дуже добре описали різницю між First()і FirstOrDefault(). Хочу зробити подальший крок у тлумаченні семантики цих методів. На мою думку FirstOrDefault, надто багато зловживають. У більшості випадків, коли ви фільтруєте дані, ви можете розраховувати отримати колекцію елементів, що відповідають логічній умові, або один унікальний елемент за його унікальним ідентифікатором - наприклад, користувачем, книгою, публікацією тощо ... Це чому ми можемо навіть сказати, що FirstOrDefault()це кодовий запах не тому, що в цьому щось не так, а тому, що він використовується занадто часто. Ця публікація в блозі детально досліджує цю тему. ІМО більшість разівSingleOrDefault() набагато краща альтернатива, тому стежте за цією помилкою і переконайтеся, що ви використовуєте найбільш підходящий метод, який чітко відображає ваш договір та очікування.


-6

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

Ось приклад, де ми можемо знайти елемент з ідентифікатором у колекції. Щоб додати більше про це, методи, По-перше, FirstOrDefaultв ідеалі повертатимуться однаково, коли колекція має принаймні один запис. Якщо, однак, колекція гаразд бути порожньою. то Firstповерне виняток, але FirstOrDefaultповерне nullабо за замовчуванням. Наприклад, intповернеться 0. Таким чином, використання таких, хоча кажуть, є особистою перевагою, але краще використовувати, FirstOrDefaultщоб уникнути обробки винятків. ось приклад, де ми переходимо до колекції списку транзакцій

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.