Kapan harus menggunakan .First dan kapan harus menggunakan .FirstOrDefault dengan LINQ?

824

Saya telah mencari-cari dan belum benar-benar menemukan jawaban yang jelas kapan Anda ingin menggunakan .Firstdan kapan Anda ingin menggunakannya .FirstOrDefaultdengan LINQ.

  • Kapan Anda ingin menggunakannya .First? Hanya ketika Anda ingin menangkap pengecualian jika tidak ada hasil yang dikembalikan?

    var result = List.Where(x => x == "foo").First();
  • Dan kapan Anda ingin menggunakannya .FirstOrDefault? Kapan Anda selalu ingin jenis default jika tidak ada hasil?

    var result = List.Where(x => x == "foo").FirstOrDefault();
  • Dan dalam hal ini, bagaimana dengan Take?

    var result = List.Where(x => x == "foo").Take(1);
Metro Smurf
sumber
86
.Firstdan .FirstOrDefaultkeduanya mengambil predikat sebagai argumen, sehingga var result = List.Where(x => x == "foo").First();dapat ditulis ulang sebagaivar result = List.First(x => x == "foo");
Rian Schmits
59
Jangan lupa untuk mempertimbangkan Singledan SingleOrDefault. Saya benci ketika orang menggunakan Firstketika mereka benar-benar berarti Single; )
BartoszKP
19
Single atau SingleOrDefault akan memberikan pengecualian jika ada lebih dari satu elemen yang dikembalikan! Saya pikir FirstOrDefault lebih baik dalam kebanyakan kasus umum!
Eric Draven
21
Intinya adalah ketika Anda mengharapkan hasil tunggal, Anda harus mengatakannya, dan pengecualian menunjukkan logika Anda gagal.
NetMage
1
Juga pertimbangkan bahwa menggunakan .FirstOrDefault()selalu memberi Anda kesempatan untuk melemparkan pengecualian yang lebih bermakna. Jika pengecualian urutan dilemparkan dan lebih dari satu .First()dalam suatu metode, mungkin sulit untuk membedakan pernyataan mana yang menjadi masalah.
StingyJack

Jawaban:

807

Saya akan menggunakan First()ketika saya tahu atau mengharapkan urutan memiliki setidaknya satu elemen. Dengan kata lain, ketika itu adalah kejadian luar biasa bahwa urutannya kosong.

Gunakan FirstOrDefault()ketika Anda tahu bahwa Anda perlu memeriksa apakah ada elemen atau tidak. Dengan kata lain, saat legal urutannya kosong. Anda tidak harus bergantung pada penanganan pengecualian untuk cek. (Ini adalah praktik buruk dan mungkin merusak kinerja).

Akhirnya, perbedaan antara First()dan Take(1)adalah yang First()mengembalikan elemen itu sendiri, sementara Take(1)mengembalikan urutan elemen yang persis mengandung satu elemen.

driis
sumber
4
@driis - Saya membayangkan kita bisa menggunakan mantra pedoman pengecualian yang luar biasa ketika memilih antara First dan FirstOrDefault. Terima kasih atas jawaban yang jelas.
Metro Smurf
5
Satu-satunya hal yang saya tambahkan adalah bahwa jika nilai default untuk jenis yang Anda pilih bisa menjadi nilai yang valid, misalnya hasil Anda mungkin nilai int 0, maka menangani pengecualian tampaknya merupakan cara terbaik untuk menangani ini .
PeterBelm
25
Gores itu, saya telah menemukan cara yang jauh lebih baik untuk mencapai itu, gunakan: DefaultIfEmpty (-1)
.First
5
Take tidak mengembalikan tepat satu elemen, ia mengembalikan paling banyak satu elemen (jika Anda menentukan 1, tentu saja). Mungkin juga mengembalikan 0 elemen, jika urutan awalnya kosong.
SPIRiT_1984
3
@RoyiNamir, ya dalam konteks pertanyaan di mana parameter yang harus diambil adalah 1. Saya juga mencatat bahwa di parens segera setelah kalimat itu.
driis
272

.Firstakan melempar pengecualian ketika tidak ada hasil. .FirstOrDefaulttidak akan, itu hanya akan mengembalikan null (tipe referensi) atau nilai default dari tipe nilai. (mis. suka 0untuk int.) Pertanyaan di sini bukanlah kapan Anda menginginkan jenis default, tetapi lebih: Anda bersedia menangani pengecualian atau menangani nilai default? Karena pengecualian harus luar biasa, FirstOrDefaultlebih disukai bila Anda tidak yakin apakah Anda akan mendapatkan hasil dari permintaan Anda. Ketika secara logis data harus ada di sana, penanganan pengecualian dapat dipertimbangkan.

Skip()dan Take()biasanya digunakan ketika mengatur paging dalam hasil. (Seperti menampilkan 10 hasil pertama, dan 10 berikutnya di halaman berikutnya, dll.)

Semoga ini membantu.

Jeroen Landheer
sumber
5
@ Joen - poin bagus tentang kasus penggunaan yang lebih baik untuk menggunakan Lewati / Ambil.
Metro Smurf
4
+1 untuk penjelasan yang .FirstOrDefaultakan mengembalikan nol untuk jenis referensi. Saya bingung tentang apa yang akan menjadi objek "default". Jawaban ini menjelaskannya.
Mike Taverne
115

.First()akan mengeluarkan pengecualian jika tidak ada baris yang dikembalikan, sementara .FirstOrDefault()akan mengembalikan nilai default ( NULLuntuk semua jenis referensi) sebagai gantinya.

Jadi, jika Anda siap dan bersedia menangani kemungkinan pengecualian, .First()tidak masalah. Jika Anda memilih untuk mengecek nilai pengembaliannya != null, itu .FirstOrDefault()adalah pilihan yang lebih baik.

Tapi saya kira ini juga sedikit preferensi pribadi. Gunakan mana yang lebih masuk akal bagi Anda dan lebih cocok dengan gaya pengkodean Anda.

marc_s
sumber
66

Pertama()

  1. Mengembalikan elemen pertama dari suatu urutan.
  2. Itu melempar kesalahan ketika Tidak ada elemen dalam hasil atau sumber adalah nol.
  3. Anda harus menggunakannya, Jika lebih dari satu elemen diharapkan dan Anda hanya menginginkan elemen pertama.

FirstOrDefault ()

  1. Mengembalikan elemen pertama dari suatu urutan, atau nilai default jika tidak ada elemen yang ditemukan.
  2. Itu melempar kesalahan Hanya jika sumbernya nol.
  3. Anda harus menggunakannya, Jika lebih dari satu elemen diharapkan dan Anda hanya menginginkan elemen pertama. Juga bagus jika hasilnya kosong.

Kami memiliki tabel UserInfos, yang memiliki beberapa catatan seperti yang ditunjukkan di bawah ini. Atas dasar tabel ini di bawah ini saya telah membuat contoh ...

Tabel UserInfo

Bagaimana cara menggunakan Pertama ()

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

Hanya ada satu catatan di mana ID == 1. Harus mengembalikan
ID catatan ini : 1 Nama Depan: Manish Nama Belakang: Dubey Email: [email protected]

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

Ada beberapa catatan di mana FName == "Rahul". Rekor pertama harus dikembalikan.
ID: 7 Nama Depan: Rahul Nama Belakang: Sharma Email: [email protected]

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

Tidak ada catatan dengan ID == 13. Kesalahan harus terjadi.
InvalidOperationException: Sequence tidak mengandung elemen

Cara Menggunakan FirstOrDefault ()

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

Hanya ada satu catatan di mana ID == 1. Harus mengembalikan
ID catatan ini : 1 Nama Depan: Manish Nama Belakang: Dubey Email: [email protected]

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

Ada beberapa catatan di mana FName == "Rahul". Rekor pertama harus dikembalikan.
ID: 7 Nama Depan: Rahul Nama Belakang: Sharma Email: [email protected]

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

Tidak ada catatan dengan ID == 13. Nilai kembali adalah nol

Semoga ini akan membantu Anda memahami kapan harus menggunakan First()atau FirstOrDefault().

Mukesh Kumar
sumber
4
Menurut pendapat saya, pernyataan "Harus terjadi kesalahan." di bawah FirstOrDefault ketiga () - contohnya menyesatkan.
Jannik
Halo, Anda menjelaskan dengan baik, tapi saya agak bingung kapan mendapatkan data dari bergabung dan ketika ID tidak ada di tabel kunci asing pada waktu itu yang mana yang digunakan? Saat ini, saya menggunakan First () tetapi setelah membaca jawaban Anda, saya tidak tahu. Tolong bantu
Brijesh Mavani
20

Pertama-tama, Takeadalah metode yang sama sekali berbeda. Ini mengembalikan IEnumerable<T>dan bukan tunggal T, jadi itu keluar.

Antara Firstdan FirstOrDefault, Anda harus menggunakan Firstketika Anda yakin bahwa suatu elemen ada dan jika tidak, maka ada kesalahan.

Omong-omong, jika urutan Anda berisi default(T)elemen (misalnya null) dan Anda perlu membedakan antara yang kosong dan elemen pertama null, Anda tidak bisa menggunakan FirstOrDefault.

Mehrdad Afshari
sumber
2
@Mehrdad - poin besar, kembali: .Pertama mengembalikan IEnumerable dan ketika tidak menggunakan FirstOrDefault.
Metro Smurf
15

Pertama:

  • Mengembalikan elemen pertama dari suatu urutan
  • Melempar pengecualian: Tidak ada elemen dalam hasilnya
  • Gunakan kapan: Ketika lebih dari 1 elemen diharapkan dan Anda hanya menginginkan yang pertama

Kesalahan FirstOrD:

  • Mengembalikan elemen pertama dari suatu urutan, atau nilai default jika tidak ada elemen yang ditemukan
  • Melempar pengecualian: Hanya jika sumbernya nol
  • Gunakan kapan: Ketika lebih dari 1 elemen diharapkan dan Anda hanya menginginkan yang pertama. Juga ok untuk hasilnya kosong

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

pengguna2051770
sumber
10

Perbedaan lain yang perlu diperhatikan adalah bahwa jika Anda men-debug aplikasi di lingkungan Produksi, Anda mungkin tidak memiliki akses ke nomor baris, jadi mengidentifikasi .First()pernyataan tertentu dalam metode yang melempar pengecualian mungkin sulit.

Pesan pengecualian juga tidak akan menyertakan ekspresi Lambda yang mungkin Anda gunakan yang akan membuat masalah lebih sulit untuk di-debug.

Itu sebabnya saya selalu menggunakan FirstOrDefault()meskipun saya tahu entri nol akan membentuk situasi yang luar biasa.

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

Pertama()

Ketika Anda tahu bahwa hasil mengandung lebih dari 1 elemen yang diharapkan dan Anda hanya harus elemen urutan pertama.

FirstOrDefault ()

FirstOrDefault () sama seperti First () kecuali itu, jika tidak ada elemen yang cocok dengan kondisi yang ditentukan daripada mengembalikan nilai default tipe dasar dari koleksi generik. Itu tidak membuang InvalidOperationException jika tidak ada elemen yang ditemukan. Tapi koleksi elemen atau urutan adalah nol daripada melempar pengecualian.

Nimesh khatri
sumber
Halo, Anda menjelaskan dengan baik, tapi saya agak bingung kapan mendapatkan data dari bergabung dan ketika ID tidak ada di tabel kunci asing pada waktu itu yang mana yang digunakan? Saat ini, saya menggunakan First () tetapi setelah membaca jawaban Anda, saya tidak tahu. Tolong bantu
Brijesh Mavani
4

Jenis fungsi ini milik operator elemen. Beberapa operator elemen berguna didefinisikan di bawah ini.

  1. First / FirstOrDefault
  2. Terakhir / Terakhir atau Kesalahan
  3. Single / SingleOrDefault

Kami menggunakan operator elemen ketika kami harus memilih satu elemen dari urutan berdasarkan kondisi tertentu. Berikut ini sebuah contoh.

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

Pertama () operator mengembalikan elemen pertama dari suatu urutan setelah memenuhi persyaratan. Jika tidak ada elemen yang ditemukan maka itu akan melempar pengecualian.

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

Operator FirstOrDefault () mengembalikan elemen pertama dari suatu urutan setelah memenuhi persyaratan. Jika tidak ada elemen yang ditemukan maka akan mengembalikan nilai default dari tipe itu.

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

Sheo Dayal Singh
sumber
dijelaskan dengan baik dengan contoh yang mudah dimengerti.
Arslan Bhatti
3

Saya menemukan sebuah situs web yang menjelaskan kebutuhan akan FirstOrDefault
http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
Jika tidak ada hasil untuk kueri, dan Anda ingin menelepon Pertama () atau Tunggal () untuk mendapatkan satu baris ... Anda akan mendapatkan pengecualian "Urutan tidak mengandung elemen".

Penafian: Saya tidak pernah menggunakan LINQ, jadi saya minta maaf jika ini jauh dari sasaran.

BATAL
sumber
2
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

Yang mana yang akan digunakan? Itu harus diputuskan oleh logika bisnis, dan bukan rasa takut akan kegagalan pengecualian / program.

Misalnya, Jika logika bisnis mengatakan bahwa kita tidak dapat memiliki transaksi nol pada hari kerja (Asumsikan). Maka Anda sebaiknya tidak mencoba menangani skenario ini dengan beberapa pemrograman cerdas. Saya akan selalu menggunakan First () di atas koleksi tersebut, dan membiarkan program gagal jika sesuatu yang lain mengacaukan logika bisnis.

Kode:

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

Saya ingin melihat komentar orang lain tentang ini.

Manish Basantani
sumber
Nilai default untuk referensi dan jenis yang dapat dibatalkan adalah nol.
dsa
Gagal dengan cepat itu baik - namun untuk skenario yang Anda gambarkan, saya lebih suka melihat Pertama, gagal, menangkap pengecualian, dan kemudian mengembalikan kesalahan yang berarti. Seperti tangkapan (InvalidOperationException e) {lempar InvalidOperationException baru ("Tidak dapat memiliki nol transaksi dalam sehari!", E)}; Tapi ya, menggunakan default untuk menghindari berurusan dengan masalah logika bisnis nyata sangat buruk.
Mathieson
1

Baiklah saya beri dua sen. Kesalahan pertama / pertama adalah saat Anda menggunakan konstruktor kedua. Saya tidak akan menjelaskan apa itu, tetapi saat itulah Anda berpotensi selalu menggunakannya karena Anda tidak ingin membuat pengecualian.

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));
Arian
sumber
Tidak persis. Konstruktor pertama banyak digunakan ketika Anda perlu mengambil hanya satu item atau harus menghindari kesalahan kompilasi ketika menetapkan hasil ke nilai yang bukan array dan Anda yakin permintaan mengembalikan tepat satu hasil. Meskipun mungkin terlihat lebih cepat untuk menggunakan konstruktor kedua daripada menggunakan .Where () (karena Anda berpikir LINQ berhenti mengevaluasi item dalam daftar setelah menemukan yang pertama), ia selalu berhenti pada elemen pertama
usr-local-ΕΨΗΕΛΩΝ
0

Yang lain telah dengan sangat baik menggambarkan perbedaan antara First()dan FirstOrDefault(). Saya ingin mengambil langkah lebih lanjut dalam menafsirkan semantik dari metode ini. Menurut pendapat saya FirstOrDefaultterlalu sering digunakan. Dalam sebagian besar kasus saat Anda memfilter data, Anda akan diharapkan untuk mendapatkan kembali kumpulan elemen yang cocok dengan kondisi logis atau elemen unik tunggal dengan pengidentifikasi unik - seperti pengguna, buku, posting dll ... Itu mengapa kita bahkan bisa mengatakan bahwa itu FirstOrDefault()adalah bau kode bukan karena ada sesuatu yang salah dengan itu tetapi karena terlalu sering digunakan. Posting blog ini mengeksplorasi topik secara rinci. IMO sebagian besar kaliSingleOrDefault() adalah alternatif yang jauh lebih baik jadi waspadalah terhadap kesalahan ini dan pastikan Anda menggunakan metode yang paling tepat yang secara jelas mewakili kontrak dan harapan Anda.

Vasil Kosturski
sumber
-6

LINQ banyak cara untuk menerapkan permintaan tunggal sederhana pada koleksi, hanya kami menulis bergabung dalam sql, filter dapat diterapkan pertama atau terakhir tergantung pada kebutuhan dan kebutuhan.

Berikut adalah contoh di mana kami dapat menemukan elemen dengan id di koleksi. Untuk menambahkan lebih banyak tentang ini, metode Pertama,, FirstOrDefaultidealnya akan kembali sama ketika koleksi memiliki setidaknya satu catatan. Namun, jika suatu koleksi boleh kosong. kemudian Firstakan mengembalikan pengecualian tetapi FirstOrDefaultakan kembali nullatau default. Misalnya, intakan mengembalikan 0. Dengan demikian penggunaan tersebut meskipun dikatakan sebagai preferensi pribadi, tetapi lebih baik digunakan FirstOrDefaultuntuk menghindari penanganan pengecualian. di sini adalah contoh di mana, kami menabrak koleksi daftar transaksi

venkat
sumber