2011-06-29 36 views
8

Tôi đang nhìn vào một số mã mà phải mất một IEnumerable<T> và chuyển đổi nó vào một List<T> để nó có thể sử dụng List<T>.Find(predicate):LINQ tương đương với Danh sách <T> .Find()?

var myEnumerable = ...; 
var myList = new List<T>(myEnumerable); 
var match = myList.Find(value => value.Aaa == aaa && value.Bbb == bbb); 

Có cách nào để viết lại này bằng cách sử dụng LINQ extension methods có tác dụng tương tự, nhưng không có xây dựng thêm List<T> làm bước trung gian?

Phương pháp mở rộng FirstOrDefault(source, predicate) trông giống như một ứng cử viên tốt, nhưng cố gắng tìm hiểu xem đó là chính xác tương đương với Find đang khiến tôi đau đầu.

Trả lời

10

Các LINQ equivelent sẽ được sử dụng FirstOrDefault:

var match = myEnumerable.FirstOrDefault(value => value.Aaa == aaa && value.Bbb == bbb); 
+0

Đó là những gì tôi nghi ngờ, nhưng thật tuyệt khi nghe xác nhận của một người có nhiều đại diện hơn tôi (cười). Vì vậy, điều này không đối phó với tất cả các trường hợp cạnh cùng một cách? (Bộ sưu tập trống, không có gì phù hợp, bất kỳ điều kiện đặc biệt nào khác) –

+0

@Joe: Có. Nó sẽ cung cấp cho bạn kết quả tương tự - kết quả đầu tiên, hoặc 'mặc định (T)' trong trường hợp không có phần tử phù hợp. Nó có hiệu quả giống hệt nhau, ngoại trừ việc nó hoạt động trên bất kỳ 'IEnumerable ' –

1

Hoặc bạn có thể làm theo cách sau:

var match = myEnumerable.Where(value => value.Aaa == aaa && value.Bbb == bbb) 
         .FirstOrDefault(); 
+0

Đây là truy vấn hai lần, điều này không cần thiết vì bạn có thể đạt được kết quả mong muốn chỉ với FirstOrDefault –

+2

@danderson: Không đúng sự thật - LINQ sử dụng thực thi trì hoãn, do đó," truy vấn "sẽ ngừng thực thi ngay khi tìm thấy phần tử đầu tiên. Điều này thực sự không kém hiệu quả hơn nhiều so với việc chỉ sử dụng FirstOrDefault trực tiếp [rất ít hiệu quả hơn, nhưng chỉ bằng kính hiển vi như vậy]. Chỉ có tối đa một lần lặp qua chuỗi ... –

+0

Tôi đã chạy một số kiểm tra hiệu năng và đã xác minh điều này, nhưng bạn cũng biết về bất kỳ bài viết, whitepapers hoặc liên kết MSDN nào giải thích cách LINQ hoạt động dưới mui xe? Tôi đã không tìm thấy bất kỳ trên MSDN nào được nêu ra –

13

Chỉ cần để tham khảo, đây là một bảng của một số cũ theo phong cách NET 2 List<> phương pháp mẫu và phương pháp mở rộng tương đương của chúng trong Linq:

METHOD IN List<>        METHOD IN Linq 
------------------------------------------------------------------------------------------ 

list.Contains(item)       query.Contains(item) 

list.Exists(x => x.IsInteresting())   query.Any(x => x.IsInteresting()) 
list.TrueForAll(x => x.IsInteresting())  query.All(x => x.IsInteresting()) 

list.Find(x => x.IsInteresting())    query.FirstOrDefault(x => x.IsInteresting()) 
list.FindLast(x => x.IsInteresting())   query.LastOrDefault(x => x.IsInteresting()) 

list.FindAll(x => x.IsInteresting())   query.Where(x => x.IsInteresting()) 

list.ConvertAll(x => x.ProjectToSomething()) query.Select(x => x.ProjectToSomething()) 

Tất nhiên một số trong số họ không hoàn toàn tương đương. Cụ thể là WhereSelect sử dụng lệnh hoãn trả chậm của LINQ, trong khi FindAllConvertAll của List<> sẽ thực hiện ngay lập tức và trả lại tham chiếu đến một phiên bản List<> mới.

FindLast thường sẽ nhanh hơn LastOrDefault vì thực tế tìm kiếm bắt đầu từ cuối List<>. Mặt khác, LastOrDefault(predicate) luôn chạy qua toàn bộ chuỗi (bắt đầu từ mục đầu tiên) và chỉ sau đó trả lại kết quả "gần đây nhất".

+2

Câu trả lời hay và nhận xét thú vị về FindLast so với LastOrDefault. –

Các vấn đề liên quan