Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

LINQ trả về gì khi kết quả rỗng trong C#

Khi LINQ query không tìm thấy phần tử nào, hành vi phụ thuộc vào phương thức thực thi (execution method).

Các trường hợp phổ biến

Phương thứcKết quả khi rỗngNém Exception?
ToList() / ToArray()Empty List/Array (Count == 0)Không
First()-Có - InvalidOperationException "Sequence contains no elements"
FirstOrDefault()default(T) (null cho reference, 0 cho int...)Không
Single()-Có - "Sequence contains no elements"
SingleOrDefault()default(T)Không
Last()-Có
LastOrDefault()default(T)Không
ElementAt(index)-Có - ArgumentOutOfRangeException
ElementAtOrDefault(index)default(T)Không
Any()falseKhông
All()true (vacuous truth)Không
Count()0Không
Sum() / Average()0 / Exception (InvalidOperationException)Average ném exception

Ví dụ minh họa


var numbers = new List { 1, 2, 3 };
var empty = numbers.Where(x => x > 10); // Empty sequence

// Safe methods
Console.WriteLine(empty.ToList().Count);           // 0
Console.WriteLine(empty.FirstOrDefault());         // 0 (default(int))
Console.WriteLine(empty.SingleOrDefault());        // 0
Console.WriteLine(empty.Any());                    // False
Console.WriteLine(empty.All(x => x > 0));          // True (vacuous truth)
Console.WriteLine(empty.Count());                  // 0
Console.WriteLine(empty.Sum());                    // 0

// Unsafe methods (throw)
// empty.First();      // InvalidOperationException
// empty.Single();     // InvalidOperationException
// empty.Average();    // InvalidOperationException

Best Practice: An toàn với kết quả rỗng


// 1. Dùng OrDefault cho single element
var first = list.FirstOrDefault(x => x > 10);
if (first != 0) { /* ... */ } // Hoặc first != default

// 2. Kiểm tra Any() trước
if (list.Any(x => x > 10))
{
    var first = list.First(x => x > 10); // Safe vì đã check Any
}

// 3. DefaultIfEmpty cho query syntax / projection
var result = from x in list.Where(x => x > 10).DefaultIfEmpty()
             select x.Name ?? "N/A";

// 4. Nullable reference types (C# 8+) giúp catch tại compile time
#nullable enable
string? firstName = list.Where(x => x > 10).Select(x => x.Name).FirstOrDefault();
// firstName có thể null -> compiler cảnh báo nếu dereference unchecked

LINQ to SQL / Entity Framework

  • FirstOrDefault(), SingleOrDefault() -> trả về null (entity class).
  • ToList() -> trả về List<T> rỗng.
  • Count() -> trả về 0.
  • Any() -> dịch sang SQL EXISTS, hiệu quả.

Tóm lại: Luôn ưu tiên các phương thức OrDefault, Any, ToList khi không chắc chắn có dữ liệu. Tránh First(), Single(), Average() trên sequence có thể rỗng.