2009-04-09 42 views
19

Sử dụng LINQ cách tốt nhất để chọn một mục từ danh sách nếu mục đó có thể không tồn tại trong danh sách là gì?Chọn một mục từ danh sách

Tôi đã đưa ra hai giải pháp, không phải trong số đó tôi thích. Tôi sử dụng mệnh đề where để chọn danh sách các mục (mà tôi biết sẽ chỉ là một), sau đó tôi có thể kiểm tra số và thực hiện một cuộc gọi đơn trên danh sách này nếu đếm là một, lựa chọn khác là sử dụng foreach và phá vỡ sau khi nhận được các mục.

Không có cách nào trong số này có vẻ là một cách tiếp cận tốt, có cách nào tốt hơn không?

Trả lời

32

Bạn có thể sử dụng IEnumerable.First() hoặc IEnumerable.FirstOrDefault().

Sự khác biệt là First() sẽ ném nếu không tìm thấy phần tử nào (hoặc nếu không có yếu tố nào phù hợp với điều kiện, nếu bạn sử dụng các điều kiện). FirstOrDefault() sẽ trả về default(T) (null nếu đó là loại tham chiếu).

+1

Rất đơn giản, không chắc chắn cách tôi bỏ qua. Cảm ơn. – Daniel

+0

nó thực sự gây nhầm lẫn, khi chúng ta có Danh sách mục và chúng ta muốn một mục từ nó dựa trên điều kiện (Where()), tên phương thức là First/FirstOrDefault, tài liệu đã nói - Trả về phần tử đầu tiên của chuỗi hoặc giá trị nếu chuỗi không chứa phần tử. Điều quan trọng là, phương thức này sẽ nhận được mục đầu tiên trong danh sách đó mà không cần lặp qua danh sách. [ref] (https://msdn.microsoft.com/en-us/library/bb340482 (v = vs.110) .aspx) –

+0

@KuganKumar Nó phải lặp lại cho đến khi nó tìm thấy một kết quả phù hợp (hoặc truy cập vào cuối và không không tìm thấy) - đó là "yếu tố khớp đầu tiên", không phải "yếu tố đầu tiên của bộ sưu tập" –

1

Có thể tôi đang thiếu thứ gì đó ở đây, nhưng thường gọi .SingleOrDefault() là cách để trả lại phần tử đơn lẻ trong danh sách hoặc giá trị mặc định (null cho tham chiếu hoặc loại có thể null). Nó tạo ra một ngoại lệ nếu danh sách chứa nhiều hơn một phần tử.

Sử dụng FirstOrDefault() để chăm sóc các trường hợp mà bạn có thể có nhiều hơn một)

8
List<string> items = new List<string>(); 

items.Find(p => p == "blah"); 

hoặc

items.Find(p => p.Contains("b")); 

nhưng điều này cho phép bạn xác định những gì bạn đang tìm kiếm thông qua một vị trận đấu ...

Tôi đoán nếu bạn đang nói linqToSql thì:

dụ tìm kiếm tài khoản ...

DataContext dc = new DataContext(); 

Account item = dc.Accounts.FirstOrDefault(p => p.id == 5); 

Nếu bạn cần phải chắc chắn rằng chỉ có 1 mục (ném ngoại lệ khi có nhiều hơn 1)

DataContext dc = new DataContext(); 

Account item = dc.Accounts.SingleOrDefault(p => p.id == 5); 
2

Có hai cách dễ dàng, tùy thuộc vào nếu bạn muốn xử lý ngoại lệ hoặc nhận giá trị mặc định.

Bạn có thể sử dụng First<T>() hoặc phương pháp mở rộng FirstOrDefault<T>() để nhận kết quả đầu tiên hoặc default(T).

var list = new List<int> { 1, 2, 4 }; 
var result = list.Where(i => i == 3).First(); // throws InvalidOperationException 
var result = list.Where(i => i == 3).FirstOrDefault(); // = 0 
14

Sử dụng bộ chọn FirstOrDefault.

var list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

var firstEven = list.FirstOrDefault(n => n % 2 == 0); 

if (firstEven == 0) 
    Console.WriteLine("no even number"); 
else 
    Console.WriteLine("first even number is {0}", firstEven); 

Chỉ cần vượt qua trong một vị đến First hoặc FirstOrDefault phương pháp và nó hạnh phúc sẽ đi vòng' danh sách và chọn trận đấu đầu tiên cho bạn.

Nếu không khớp, FirstOrDefault sẽ trả về giá trị mặc định của bất kỳ loại dữ liệu nào mà các mục danh sách.

Hope this helps :-)

0

SingleOrDefault() là những gì bạn cần

cổ vũ

4

Chỉ cần để hoàn thành câu trả lời, Nếu bạn đang sử dụng cú pháp LINQ, bạn chỉ có thể quấn nó vì nó trả về một IEnumerable:

(from int x in intList 
where x > 5 
select x * 2).FirstOrDefault() 
0

chỉ thấy này ngay bây giờ, nếu bạn đang làm việc với một danh sách các đối tượng bạn có thể thử

này
public class user 
{ 
    public string username { get; set; } 
    public string password { get; set; } 
} 

    List<user> userlist = new List<user>(); 

     userlist.Add(new user { username = "macbruno", password = "1234" }); 
     userlist.Add(new user { username = "james", password = "5678" }); 
     string myusername = "james"; 
     string mypassword = "23432"; 

    user theUser = userlist.Find(
      delegate (user thisuser) 
      { 
       return thisuser.username== myusername && thisuser.password == mypassword; 
      } 
      ); 

      if (theUser != null) 
      { 
       Dosomething(); 
      } 
      else 
      { 
       DoSomethingElse(); 

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