2011-11-28 32 views
5

trong ứng dụng Silverlight 4 của tôi, tôi có một ObservableCollection trong đó bao gồm các đối tượng của một lớp và được xác định bởi một giao diện:Sử dụng Lambda biểu trên một ObservableCollection

interface myInterface() 
{ 
    string Name { get; set; } 
    string Value { get; set; } 
} 

class myClass() : myInterface 
{ 
    ... 
} 

ObservableCollection<myInterface> _collection; 

Trước khi thêm một yếu tố mới cho bộ sưu tập, tôi muốn đảm bảo rằng Tên-Thuộc tính không tồn tại trong các phần tử sưu tập hiện tại. Vì tôi không thể làm việc với chứa, tôi hiện đang lặp qua tất cả các phần tử và kiểm tra từng phần tử theo cách thủ công.

private bool CollectionContainsElement(string name2CheckAgainst) 
{ 
    foreach (myInterface item in _collection) 
    if (item.Name.Equals(name2CheckAgainst)) 
     return true; 

    return false; 
} 

Tôi đã đọc rằng điều này cũng có thể đạt được thông qua một biểu thức Lambda, vì vậy tôi đã viết như sau:

if (!_collection.Contains(p => p.Name == name2CheckAgainst)) 
{ 
    ... 

Nhưng bây giờ tôi nhận được một lỗi, nói rằng "biểu thức lambda không thể được chuyển thành Kiểu "myInterface", vì nó không có kiểu đại biểu ". (Từ ngữ có thể khác nhau, khi tôi dịch từ phiên bản tiếng Đức)

Tôi không chắc chắn những gì tôi phải thay đổi để làm cho nó hoạt động. using System.Linq; được bao gồm. Và câu hỏi thứ hai (hoặc có thể là câu hỏi chính): tôi đã đọc, rằng thời gian chạy thay đổi từ O (1) cho phương thức Contains() thành O (n) - không nhanh hơn kiểm tra hiện tại của tôi. Vì vậy, nó thậm chí có ý nghĩa để thay đổi nó để sử dụng lambda? Và cuối cùng, có lẽ có một phương pháp khác trong việc kiểm tra một Tên-Tài sản hiện có trong lớp của tôi không?

Cảm ơn trước,
Frank

Trả lời

15
  1. Bạn không cần phải viết một phương pháp Chứa thì Bất kỳ phương pháp của LINQ đã được làm điều đó:

    if (!_collection.Any(p => p.Name == name2CheckAgainst)) 
    
  2. Nếu bạn muốn sử dụng một Lambda, bạn phải thay đổi nguyên mẫu các bạn phương pháp Chứa chấp nhận một lambda (một lambda chỉ là một cách khác để viết một chức năng ẩn danh):

    private bool CollectionContainsElement(Func<myInterface, bool> lambda) 
    { 
        foreach (myInterface item in _collection) 
        if (lambda(item)) 
         return true; 
    
        return false; 
    } 
    
  3. Sử dụng một lambda đây không làm thay đổi mức độ phức tạp của functi của bạn trên, nó là O (n) trong cả hai trường hợp. Vì vậy, nó chỉ là vấn đề sở thích.

+0

cảm ơn rất nhiều, có vẻ như tôi đã đọc sai ví dụ về lamda trong phương thức chứa. Sử dụng Any là hiển nhiên :) – Aaginor

2

Bạn có thể sử dụng Linq Any() method. Đó là sử dụng được như vậy:

if (!_collection.Any(p => p.Name == name2CheckAgainst)) 
{ 
} 

Lý do tại sao chứa phương pháp là O (1) là dưới tấm chăn nó tải bộ sưu tập của bạn thành một Hashtable (hoặc tương tự) và sử dụng mã băm (tiếp theo là một cuộc gọi để Bằng) để kiểm tra xem một phần tử có hiện diện hay không.

1

Chứa không phải là phần mở rộng LINQ và do đó bạn không thể sử dụng biểu thức lambda với nó. Nó được thiết kế để kiểm tra nếu được cung cấp đối tượng tồn tại trong danh sách.

Như những người khác đã nói, Bất kỳ là phương pháp mở rộng tương thích với biểu thức lambda tương đương

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