Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ความแตกต่างระหว่าง Last() และ LastOrDefault() ใน LINQ C#

Last() vs LastOrDefault() ใน LINQ

ทั้งสองเมธอดใช้ดึง Element ตัวสุดท้าย ของ Sequence ที่ตรงเงื่อนไข แตแตกต่างที่พฤติกรรมเมื่อ ไม่พบข้อมูล

ความแตกต่างหลัก

เมธอดพบข้อมูลไม่พบข้อมูล (Empty Sequence)โยน Exception?
Last()คืน Element ตัวสุดท้ายโยน InvalidOperationException✅ ใช่
LastOrDefault()คืน Element ตัวสุดท้ายคืน default(T) (null/0/false)❌ ไม่

ตัวอย่างที่ 1: พบข้อมูล (เหมือนกัน)


using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var students = new List
        {
            new Student { Id = 1, Name = "John" },
            new Student { Id = 2, Name = "Jack" },
            new Student { Id = 1, Name = "Jill" }  // Id=1 ซ้ำ
        };
        
        // หา Id = 1 ตัวสุดท้าย
        var lastOrDefault = students.LastOrDefault(s => s.Id == 1);
        var last = students.Last(s => s.Id == 1);
        
        Console.WriteLine($"LastOrDefault: Id={lastOrDefault.Id}, Name={lastOrDefault.Name}");
        Console.WriteLine($"Last: Id={last.Id}, Name={last.Name}");
    }
}

class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

ผลลัพธ์:

LastOrDefault: Id=1, Name=Jill
Last: Id=1, Name=Jill

ตัวอย่างที่ 2: ไม่พบข้อมูล (ต่างกัน)


using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var students = new List
        {
            new Student { Id = 1, Name = "John" },
            new Student { Id = 2, Name = "Jack" }
        };
        
        // หา Id = 3 (ไม่มี)
        Console.WriteLine("=== LastOrDefault ===");
        var lastOrDefault = students.LastOrDefault(s => s.Id == 3);
        Console.WriteLine($"Result: {lastOrDefault?.Name ?? "null"}");  // null
        Console.WriteLine($"Is Null: {lastOrDefault == null}");  // True
        
        Console.WriteLine("\n=== Last ===");
        try
        {
            var last = students.Last(s => s.Id == 3);
            Console.WriteLine($"Result: {last.Name}");
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"Exception: {ex.Message}");  // Sequence contains no matching element
        }
    }
}

class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

ผลลัพธ์:

=== LastOrDefault ===
Result: null
Is Null: True

=== Last ===
Exception: Sequence contains no matching element

เมื่อไหร่ควรใช้ตัวไหน?

✅ ใช้ Last() เมื่อ:

  • มั่นใจว่า ต้องมีข้อมูลอย่างน้อย 1 รายการ ตรงเงื่อนไข
  • ข้อมูลว่างเป็น Bug/Exceptional Case ที่ควร Fail Fast
  • Domain Logic กำหนดว่าต้องมีข้อมูลเสมอ (เช่น Primary Key Lookup)

✅ ใช้ LastOrDefault() เมื่อ:

  • ไม่แน่ใจ ว่ามีข้อมูลหรือไม่
  • ข้อมูลว่างเป็น Normal Case (Optional Data)
  • ต้องการ Handle เอง (Null Check, Default Value, Alternative Logic)

Default Values สำหรับ Type ต่างๆ

Typedefault(T)
Reference Type (class, string, array, delegate)null
Value Type (int, bool, DateTime, struct)0, false, DateTime.MinValue, zero-initialized
Nullable<T> (T?)null

Pattern Matching (C# 7+) สำหรับ LastOrDefault


// Pattern Matching Null Check
var student = students.LastOrDefault(s => s.Id == 3);

if (student is { } foundStudent)
{
    Console.WriteLine($"Found: {foundStudent.Name}");
}
else
{
    Console.WriteLine("Not found");
}

// Switch Expression (C# 8+)
var message = student switch
{
    { Id: > 0 } => $"Found: {student.Name}",
    _ => "Not found"
};

คู่หู: First() vs FirstOrDefault()

เหมือนกันเป๊ะๆ แต่สำหรับ Element ตัวแรก:

เมธอดไม่พบข้อมูล
First()โยน InvalidOperationException
FirstOrDefault()คืน default(T)
Single()โยน Exception (ถ้า 0 หรือ >1)
SingleOrDefault()คืน default(T) (ถ้า 0) / โยน Exception (ถ้า >1)

Best Practices

  1. Default to LastOrDefault/FirstOrDefault - ปลอดภัยกว่า
  2. ใช้ Last() เฉพาะเมื่อ Domain Logic รับประกันว่ามีข้อมูล
  3. หลัง LastOrDefault() ต้อง Null Check เสมอ ก่อนเข้าถึง Property
  4. พิจารณา Single/SingleOrDefault หากคาดหวัง Unique Result (Primary Key)

สรุป

  • Last() - Strict, โยน Exception ถ้าว่าง → Fail Fast
  • LastOrDefault() - Lenient, คืน null/0 → Defensive
  • เลือกตาม Business Rule: "ข้อมูลว่างเป็น Error หรือ Normal?"
  • คู่หู: First/FirstOrDefault, Single/SingleOrDefault