เมื่อใดควรใช้. ก่อนอื่นและควรใช้. FirstOrDefault กับ LINQ หรือไม่


824

ฉันค้นหาไปรอบ ๆ แล้วและไม่พบคำตอบที่ชัดเจนว่าเมื่อใดที่คุณต้องการใช้.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);

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 ดีกว่าในกรณีส่วนใหญ่!
Eric Draven

21
จุดคือเมื่อคุณคาดหวังผลลัพธ์เดียวที่คุณควรพูดอย่างนั้นและข้อยกเว้นบ่งชี้ว่าตรรกะของคุณล้มเหลว
NetMage

1
นอกจากนี้ให้พิจารณาว่าการใช้.FirstOrDefault()เสมอเปิดโอกาสให้คุณโยนข้อยกเว้นที่มีความหมายมากขึ้น หากมีการโยนข้อยกเว้นตามลำดับและมีมากกว่าหนึ่งรายการ.First()ในวิธีการหนึ่งอาจเป็นการยากที่จะแยกแยะว่าคำสั่งใดเป็นปัญหา
StingyJack

คำตอบ:


807

ฉันจะใช้First()เมื่อฉันรู้หรือคาดหวังว่าลำดับจะมีองค์ประกอบอย่างน้อยหนึ่งรายการ กล่าวอีกนัยหนึ่งเมื่อมันเกิดขึ้นเป็นพิเศษว่าลำดับที่ว่างเปล่า

ใช้FirstOrDefault()เมื่อคุณรู้ว่าคุณจะต้องตรวจสอบว่ามีองค์ประกอบหรือไม่ ในคำอื่น ๆ เมื่อมันถูกกฎหมายสำหรับลำดับที่จะว่างเปล่า คุณไม่ควรเชื่อถือข้อยกเว้นสำหรับการตรวจสอบ (เป็นการปฏิบัติที่ไม่ดีและอาจส่งผลต่อประสิทธิภาพ)

ในที่สุดความแตกต่างระหว่างFirst()และTake(1)คือการFirst()ส่งคืนองค์ประกอบเองในขณะที่Take(1)ส่งกลับลำดับขององค์ประกอบที่มีองค์ประกอบหนึ่งอย่างแน่นอน


4
@driis - ฉันคิดว่าเราสามารถใช้มนต์ของแนวทางข้อยกเว้นพิเศษเมื่อเลือกระหว่าง First และ FirstOrDefault ขอบคุณสำหรับคำตอบที่ชัดเจน
Metro Smurf

5
สิ่งเดียวที่ฉันเพิ่มคือถ้าค่าเริ่มต้นสำหรับประเภทที่คุณเลือกอาจเป็นค่าที่ถูกต้องตัวอย่างเช่นผลลัพธ์ของคุณอาจเป็นค่า int 0 จากนั้นการจัดการข้อยกเว้นน่าจะเป็นวิธีที่ดีที่สุดในการจัดการสิ่งนี้ .
PeterBelm

25
เกาว่าฉันพบวิธีที่ดีกว่ามากในการทำสิ่งนั้นให้ใช้: DefaultIfEmpty (-1)
.First

5
Take ไม่ส่งคืนองค์ประกอบหนึ่งเดียว แต่จะส่งคืนได้มากที่สุดหนึ่งองค์ประกอบ (หากคุณระบุ 1 แน่นอน) มันอาจส่งคืนองค์ประกอบ 0 เช่นกันถ้าลำดับนั้นว่างเปล่าในตอนแรก
SPIRiT_1984

3
@RoyiNamir ใช่ในบริบทของคำถามที่พารามิเตอร์ใช้คือ 1 ฉันยังตั้งข้อสังเกตว่าใน parens ทันทีหลังจากประโยคนั้น
driis

272

.Firstจะโยนข้อยกเว้นเมื่อไม่มีผลลัพธ์ .FirstOrDefaultไม่มันจะคืนค่าเป็น null (ชนิดอ้างอิง) หรือค่าเริ่มต้นของประเภทค่า (เช่นต้องการ0int) คำถามที่นี่ไม่ใช่เมื่อคุณต้องการประเภทเริ่มต้น แต่เพิ่มเติม: คุณยินดีที่จะจัดการข้อยกเว้นหรือจัดการค่าเริ่มต้นหรือไม่ เนื่องจากข้อยกเว้นควรเป็นข้อยกเว้นคุณควรFirstOrDefaultเลือกเมื่อคุณไม่แน่ใจว่าคุณจะได้ผลลัพธ์จากการสืบค้น เมื่อมีเหตุผลข้อมูลควรมีการจัดการข้อยกเว้นสามารถพิจารณา

Skip()และTake()โดยปกติจะใช้เมื่อตั้งค่าการเพจในผลลัพธ์ (เช่นแสดงผลลัพธ์ 10 รายการแรกและอีก 10 รายการในหน้าถัดไป ฯลฯ )

หวังว่านี่จะช่วยได้


5
@Jeroen - จุดดีในกรณีการใช้ที่ดีกว่าสำหรับการใช้ข้าม / ใช้
Metro Smurf

4
+1 สำหรับคำอธิบายที่.FirstOrDefaultจะคืนค่า null สำหรับประเภทการอ้างอิง ฉันสับสนเกี่ยวกับสิ่งที่ "เริ่มต้น" วัตถุจะ คำตอบนี้ถูกลบทิ้ง
Mike Taverne

115

.First()จะโยนข้อยกเว้นหากไม่มีแถวที่จะส่งคืนขณะที่.FirstOrDefault()จะส่งคืนค่าเริ่มต้น ( NULLสำหรับประเภทการอ้างอิงทั้งหมด) แทน

ดังนั้นถ้าคุณเตรียมความพร้อมและยินดีที่จะจัดการกับข้อยกเว้นที่เป็นไปได้.First()ดี หากคุณต้องการที่จะตรวจสอบค่าตอบแทนสำหรับการ!= nullต่อไปจากนั้น.FirstOrDefault()เป็นทางเลือกที่ดีของคุณ

แต่ฉันคิดว่ามันเป็นความชอบส่วนตัวเช่นกัน ใช้วิธีใดก็ได้ที่เหมาะสมกับคุณและเหมาะกับสไตล์การเขียนโค้ดของคุณดีขึ้น


66

แรก ()

  1. ส่งคืนองค์ประกอบแรกของลำดับ
  2. มันจะโยนข้อผิดพลาดเมื่อไม่มีองค์ประกอบในผลลัพธ์หรือแหล่งที่มาเป็นโมฆะ
  3. คุณควรใช้มันหากคาดว่ามีมากกว่าหนึ่งองค์ประกอบและคุณต้องการเพียงองค์ประกอบแรกเท่านั้น

FirstOrDefault ()

  1. ส่งคืนองค์ประกอบแรกของลำดับหรือค่าเริ่มต้นหากไม่พบองค์ประกอบ
  2. มันจะโยนข้อผิดพลาดเฉพาะถ้าแหล่งที่มาเป็นโมฆะ
  3. คุณควรใช้มันหากคาดว่ามีมากกว่าหนึ่งองค์ประกอบและคุณต้องการเพียงองค์ประกอบแรกเท่านั้น ยังดีถ้าผลลัพธ์ว่างเปล่า

เรามีตาราง UserInfos ซึ่งมีบันทึกบางส่วนตามที่แสดงด้านล่าง บนพื้นฐานของตารางนี้ด้านล่างฉันได้สร้างตัวอย่าง ...

ตาราง UserInfo

วิธีใช้ First ()

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

มีเพียงหนึ่งระเบียนที่ ID == 1. ควรส่งคืนระเบียนนี้
ID: 1 ชื่อ: Manish นามสกุล: Dubey อีเมล: xyz@xyz.com

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

มีหลายระเบียนที่ FName == "Rahul" บันทึกแรกควรกลับมา
ID: 7 ชื่อ: Rahul นามสกุล: Sharma อีเมล: xyz1@xyz.com

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

ไม่มีบันทึกที่มี ID == 13. ข้อผิดพลาดควรเกิดขึ้น
InvalidOperationException: ลำดับไม่มีองค์ประกอบ

วิธีใช้ FirstOrDefault ()

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

มีเพียงหนึ่งระเบียนที่ ID == 1. ควรส่งคืนระเบียนนี้
ID: 1 ชื่อ: Manish นามสกุล: Dubey อีเมล: xyz@xyz.com

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

มีหลายระเบียนที่ FName == "Rahul" บันทึกแรกควรกลับมา
ID: 7 ชื่อ: Rahul นามสกุล: Sharma อีเมล: xyz1@xyz.com

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

ไม่มีเร็กคอร์ดที่มี ID == 13. ค่าส่งคืนเป็น null

หวังว่ามันจะช่วยให้คุณเข้าใจเมื่อจะใช้หรือFirst()FirstOrDefault()


4
ในความคิดของฉันคำว่า "มีข้อผิดพลาดเกิดขึ้น" ภายใต้ FirstOrDefault ที่สาม () - ตัวอย่างทำให้เข้าใจผิด
Jannik

สวัสดีคุณอธิบายได้ดี แต่ฉันรู้สึกสับสนเล็กน้อยเมื่อได้รับข้อมูลจากการเข้าร่วมและเมื่อ ID ไม่มีอยู่ในตารางคีย์ต่างประเทศในขณะนั้นใช้รหัสใด ขณะนี้ฉันกำลังใช้ First () แต่หลังจากอ่านคำตอบของคุณแล้วฉันไม่มีความคิดโปรดช่วย
Brijesh Mavani

20

ก่อนอื่นTakeเป็นวิธีที่แตกต่างอย่างสิ้นเชิง มันส่งคืนIEnumerable<T>และไม่ใช่ซิงเกิลTดังนั้นจึงออก

ระหว่างFirstและFirstOrDefaultคุณควรใช้Firstเมื่อคุณแน่ใจว่ามีองค์ประกอบอยู่และหากไม่เป็นเช่นนั้นแสดงว่ามีข้อผิดพลาด

อย่างไรก็ตามถ้าลำดับของคุณมีdefault(T)องค์ประกอบ (เช่นnull) และคุณจำเป็นต้องแยกแยะระหว่างความว่างเปล่าและองค์ประกอบแรกnullคุณไม่สามารถใช้งานFirstOrDefaultได้


2
@ Mehrdad - จุดที่ยอดเยี่ยมอีกครั้ง: .First ส่งกลับ IEnumerable และเมื่อไม่ใช้ FirstOrDefault
Metro Smurf

15

ครั้งแรก:

  • ส่งคืนองค์ประกอบแรกของลำดับ
  • ส่งข้อยกเว้น: ไม่มีองค์ประกอบในผลลัพธ์
  • ใช้เมื่อ: คาดว่าเมื่อมีมากกว่า 1 องค์ประกอบและคุณต้องการเฉพาะองค์ประกอบแรกเท่านั้น

FirstOrDefault:

  • ส่งคืนองค์ประกอบแรกของลำดับหรือค่าเริ่มต้นหากไม่พบองค์ประกอบ
  • โยนข้อยกเว้น: เฉพาะถ้าแหล่งที่มาเป็นโมฆะ
  • ใช้เมื่อ: คาดว่าเมื่อมีมากกว่า 1 องค์ประกอบและคุณต้องการเฉพาะองค์ประกอบแรกเท่านั้น นอกจากนี้มันก็โอเคสำหรับผลลัพธ์ที่จะว่างเปล่า

จาก: http://www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/


10

ข้อแตกต่างที่ควรทราบอีกประการหนึ่งคือหากคุณดีบักแอปพลิเคชันในสภาพแวดล้อมการผลิตคุณอาจไม่สามารถเข้าถึงหมายเลขบรรทัดได้ดังนั้นการระบุ.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));
}

5

แรก ()

เมื่อคุณทราบว่าผลลัพธ์มีองค์ประกอบมากกว่า 1 รายการที่คาดหวังและคุณควรเป็นองค์ประกอบลำดับแรกเท่านั้น

FirstOrDefault ()

FirstOrDefault () ก็เหมือนกับ First () ยกเว้นว่าถ้าไม่มีองค์ประกอบใดตรงกับเงื่อนไขที่ระบุกว่าจะส่งคืนค่าเริ่มต้นของประเภทการรวบรวมทั่วไป มันจะไม่โยน InvalidOperationException หากไม่พบองค์ประกอบ แต่คอลเลกชันขององค์ประกอบหรือลำดับนั้นเป็นโมฆะกว่าข้อผิดพลาด


สวัสดีคุณอธิบายได้ดี แต่ฉันรู้สึกสับสนเล็กน้อยเมื่อได้รับข้อมูลจากการเข้าร่วมและเมื่อ ID ไม่มีอยู่ในตารางคีย์ต่างประเทศในขณะนั้นใช้รหัสใด ขณะนี้ฉันกำลังใช้ First () แต่หลังจากอ่านคำตอบของคุณแล้วฉันไม่มีความคิดโปรดช่วย
Brijesh Mavani

4

ฟังก์ชันประเภทนี้เป็นของผู้ประกอบการองค์ประกอบ ผู้ประกอบการองค์ประกอบที่มีประโยชน์กำหนดไว้ด้านล่าง

  1. แรก / FirstOrDefault
  2. ล่าสุด / LastOrDefault
  3. เดี่ยว / SingleOrDefault

เราใช้ตัวดำเนินการองค์ประกอบเมื่อเราจำเป็นต้องเลือกองค์ประกอบเดียวจากลำดับตามเงื่อนไขที่แน่นอน นี่คือตัวอย่าง

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

ตัวดำเนินการ First () ส่งคืนองค์ประกอบแรกของลำดับหลังจากที่ตรงตามเงื่อนไข หากไม่พบองค์ประกอบจะมีข้อผิดพลาดเกิดขึ้น

int ผลลัพธ์ = items.Where (item => item == 2) .First ();

ตัวดำเนินการ FirstOrDefault () ส่งคืนองค์ประกอบแรกของลำดับหลังจากปฏิบัติตามเงื่อนไข หากไม่พบองค์ประกอบก็จะส่งคืนค่าเริ่มต้นของประเภทนั้น

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


อธิบายอย่างดีด้วยตัวอย่างที่เข้าใจง่าย
Arslan Bhatti

3

ฉันพบเว็บไซต์ที่มี apperars เพื่ออธิบายความต้องการ FirstOrDefault
http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
หากไม่มีผลการสืบค้นและคุณต้องการโทรหา First () หรือ Single () เพื่อรับแถวเดียว ... คุณจะได้รับข้อยกเว้น“ Sequence ไม่มีองค์ประกอบ”

คำเตือน: ฉันไม่เคยใช้ 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()

ฉันต้องการที่จะเห็นคนอื่นแสดงความคิดเห็นมากกว่านี้


ค่าเริ่มต้นสำหรับการอ้างอิงและประเภท nullable เป็นโมฆะ
dsa

ความล้มเหลวอย่างรวดเร็วนั้นเป็นเรื่องที่ดี - อย่างไรก็ตามสำหรับสถานการณ์ที่คุณอธิบายไว้ฉันอยากจะเห็นก่อนว่ามันล้มเหลว, จับข้อยกเว้นแล้วส่งกลับข้อผิดพลาดที่มีความหมาย กดไลค์ (InvalidOperationException e) {ส่ง InvalidOperationException ใหม่ ("ไม่สามารถทำธุรกรรมได้ในหนึ่งวัน!", e)}; แต่ใช่การใช้ค่าเริ่มต้นเพื่อหลีกเลี่ยงการจัดการกับปัญหาตรรกะทางธุรกิจจริงนั้นแย่มาก
Mathieson

1

ตกลงให้ฉันให้สองเซ็นต์ของฉัน First / Firstordefault ใช้สำหรับเมื่อคุณใช้ Constructor ที่สอง ฉันจะไม่อธิบายว่ามันคืออะไร แต่มันก็เป็นเมื่อคุณอาจจะใช้หนึ่งเพราะคุณไม่ต้องการที่จะทำให้เกิดข้อยกเว้น

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

ไม่แน่นอน Constructor ตัวแรกถูกใช้อย่างกว้างขวางเมื่อคุณต้องการเรียกคืนเพียงหนึ่งไอเท็มหรือต้องหลีกเลี่ยงข้อผิดพลาดในการคอมไพล์เมื่อกำหนดผลลัพธ์ให้กับค่าที่ไม่ใช่อาเรย์และคุณแน่ใจว่าการค้นหาส่งคืนผลลัพธ์เดียว ในขณะที่มันอาจดูเร็วกว่าที่จะใช้ตัวสร้างที่สองแทนที่จะใช้เพิ่มเติม. Where () (เพราะคุณคิดว่า LINQ หยุดการประเมินรายการในรายการหลังจากหาคนแรก) มันมักจะหยุดที่องค์ประกอบแรก
usr-local-ΕΨΗΕΛΩΝ

0

คนอื่น ๆ ได้อธิบายไว้อย่างดีแตกต่างระหว่างและFirst() FirstOrDefault()ฉันต้องการใช้ขั้นตอนต่อไปในการตีความหมายของวิธีการเหล่านี้ ในความคิดของฉันFirstOrDefaultถูกใช้มากเกินไป ในกรณีส่วนใหญ่เมื่อคุณกำลังกรองข้อมูลคุณอาจคาดว่าจะได้รับคอลเลกชันขององค์ประกอบที่ตรงกับเงื่อนไขเชิงตรรกะหรือองค์ประกอบที่ไม่ซ้ำกันเดียวโดยตัวระบุที่ไม่ซ้ำกัน - เช่นผู้ใช้หนังสือโพสต์ ฯลฯ ... ทำไมเราถึงได้บอกว่าFirstOrDefault()มันเป็นรหัสกลิ่นไม่ใช่เพราะมีบางอย่างผิดปกติกับมัน แต่เพราะมันถูกใช้บ่อยเกินไป โพสต์บล็อกนี้สำรวจหัวข้อในรายละเอียด IMO เกือบทุกครั้งSingleOrDefault() เป็นทางเลือกที่ดีกว่ามากดังนั้นระวังข้อผิดพลาดนี้และให้แน่ใจว่าคุณใช้วิธีการที่เหมาะสมที่สุดที่แสดงถึงสัญญาและความคาดหวังของคุณอย่างชัดเจน


-6

linq มีหลายวิธีในการสร้างแบบสอบถามแบบง่าย ๆ เพียงครั้งเดียวบนคอลเลกชั่นเพียงแค่เราเขียนตัวกรองเป็น sql ตัวกรองสามารถถูกนำไปใช้ก่อนหรือหลังก็ได้ขึ้นอยู่กับความต้องการและความจำเป็น

นี่คือตัวอย่างที่เราสามารถหาองค์ประกอบที่มี ID ในคอลเลกชัน เมื่อต้องการเพิ่มข้อมูลเพิ่มเติมเกี่ยวกับสิ่งนี้วิธีแรกFirstOrDefaultจะกลับมาเหมือนกันโดยสมบูรณ์เมื่อมีการรวบรวมอย่างน้อยหนึ่งระเบียน อย่างไรก็ตามหากคอลเล็กชันนั้นว่างเปล่า จากนั้นFirstจะส่งคืนข้อยกเว้น แต่FirstOrDefaultจะส่งคืนnullหรือเป็นค่าเริ่มต้น ตัวอย่างเช่นintจะส่งคืน 0 ดังนั้นการใช้งานดังกล่าวถึงแม้ว่าจะกล่าวว่าเป็นความชอบส่วนตัว แต่ก็ควรใช้FirstOrDefaultเพื่อหลีกเลี่ยงข้อยกเว้นในการจัดการ นี่คือตัวอย่างที่เราเรียกใช้คอลเลกชันของรายการธุรกรรม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.