2013-06-04 35 views
6

Tôi có phương thức sau đây trả về một IEnumerable loại T. Việc triển khai phương pháp này không quan trọng, ngoài số yield return đến tải chậm số IEnumerable. Điều này là cần thiết vì kết quả có thể có hàng triệu mặt hàng.Kiểm tra xem IEnumerable có BẤT CỨ hàng nào mà không liệt kê toàn bộ danh sách

public IEnumerable<T> Parse() 
{ 
    foreach(...) 
    { 
     yield return parsedObject; 
    } 
} 

Vấn đề:

Tôi có tài sản sau đây có thể được sử dụng để xác định xem IEnumerable sẽ có bất kỳ hạng mục:

public bool HasItems 
{ 
    get 
    { 
     return Parse().Take(1).SingleOrDefault() != null; 
    } 
} 

Có lẽ một cách tốt hơn để làm điều này ?

+1

có thể trùng lặp của [Howto: Đếm các mục từ một IEnumerable mà không iterating] (http: // stackoverflow .com/questions/168901/howto-count-the-items-từ-a-ienumerablet-without-iterating) – drzaus

Trả lời

22

IEnumerable.Any() sẽ trả về true nếu có bất kỳ phần tử nào trong chuỗi và false nếu không có phần tử nào trong chuỗi. Phương thức này sẽ không lặp lại toàn bộ chuỗi (chỉ tối đa một phần tử) vì nó sẽ trả về true nếu nó vượt qua phần tử đầu tiên và false nếu nó không.

+0

Ồ, tôi không bao giờ biết về sự quá tải này của 'Bất kỳ'. Nhưng nó sẽ không phải lặp lại ít nhất một lần? – davenewza

+0

Không, nó không lặp lại. Phương thức Any sẽ trả về true nếu nó vượt qua mục đầu tiên. – Marcus

+3

Điều này không chính xác. Nó bắt đầu lặp lại số đếm, tuy nhiên nó không lặp lại toàn bộ điều. – Uatec

1

Tương tự như Howto: Count the items from a IEnumerable<T> without iterating? một Enumerable được hiểu là một lười biếng, đọc-forward "danh sách", và giống như cơ học lượng tử hành động điều tra nó làm thay đổi trạng thái của nó.

Xem xác nhận: https://dotnetfiddle.net/GPMVXH

var sideeffect = 0; 
    var enumerable = Enumerable.Range(1, 10).Select(i => { 
     // show how many times it happens 
     sideeffect++; 
     return i; 
    }); 

    // will 'enumerate' one item! 
    if(enumerable.Any()) Console.WriteLine("There are items in the list; sideeffect={0}", sideeffect); 

enumerable.Any() là cách sạch nhất để kiểm tra xem có bất kỳ mục trong danh sách. Bạn có thể thử truyền tới thứ gì đó không lười, như if(null != (list = enumerable as ICollection<T>) && list.Any()) return true.

Hoặc, kịch bản của bạn có thể cho phép sử dụng một Enumerator và thực hiện một kiểm tra sơ bộ trước khi liệt kê:

var e = enumerable.GetEnumerator(); 
// check first 
if(!e.MoveNext()) return; 
// do some stuff, then enumerate the list 
do { 
    actOn(e.Current); // do stuff with the current item 
} while(e.MoveNext()); // stop when we don't have anything else 
+0

Và cập nhật fiddle với điều tra cho thấy kiểm tra sơ bộ, trong khi vẫn đánh giá số đếm 1 lần (tức là 'sideeffect ++') không cho kết quả trong liệt kê _extra_: https://dotnetfiddle.net/no3WoH – drzaus