2011-11-28 16 views
5

nella mia applicazione Silverlight 4, ho un ObservableCollection che consiste in oggetti di una classe ed è definito da un'interfaccia:Utilizzando Lambda Expression su un ObservableCollection

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

class myClass() : myInterface 
{ 
    ... 
} 

ObservableCollection<myInterface> _collection; 

Prima di aggiungere un nuovo elemento alla collezione, ho voglio essere sicuro che la proprietà Name non esista già all'interno degli attuali elementi della collezione. Poiché non riesco a lavorare con contiene, attualmente eseguo l'iterazione di tutti gli elementi e controllo ogni elemento manualmente.

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

    return false; 
} 

Ho letto che questo può essere ottenuto anche attraverso un'espressione lambda, così ho scritto il seguente:

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

Ma ora ho un errore, dicendo che il "espressione lambda non potrebbe essere convertito nel tipo "myInterface", perché non è un tipo delegato ". (La formulazione potrebbe essere diversa, dato che l'ho tradotta dalla versione tedesca)

Non sono sicuro di quello che devo cambiare per farlo funzionare. using System.Linq; è incluso. E la seconda domanda (o forse la domanda principale): ho letto che il runtime cambia da O (1) per il metodo Contains() - a O (n) - che non è più veloce del mio controllo corrente. Quindi ha senso cambiarlo con l'uso del lambda? E infine, c'è probabilmente un altro metodo per verificare la presenza di una proprietà nome esistente nella mia classe?

Grazie in anticipo,
Frank

risposta

15
  1. Non è necessario scrivere un metodo Contiene, il Qualsiasi metodo di LINQ è già facendo:

    if (!_collection.Any(p => p.Name == name2CheckAgainst)) 
    
  2. Se si desidera utilizzare un Lambda, è necessario modificare il prototipo Contiene del vostro metodo per accettare una lambda (un lambda è solo un modo alternativo di scrivere una funzione anonima):

    private bool CollectionContainsElement(Func<myInterface, bool> lambda) 
    { 
        foreach (myInterface item in _collection) 
        if (lambda(item)) 
         return true; 
    
        return false; 
    } 
    
  3. Utilizzando un lambda qui non cambia la complessità del functi acceso, è O (n) in entrambi i casi. Quindi è solo una questione di preferenza.

+0

molte grazie, sembra che abbia letto male l'esempio withe il Lamda nella contiene metodo. Usare Any è ovvio :) – Aaginor

2

È possibile utilizzare la Linq Any() method. Quale è utilizzabile in questo modo:

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

Il motivo per cui il metodo contiene è O (1) è che sotto le coperte si carica la collezione in un HashTable (o simili) e utilizza il codice hash (seguita da una chiamata to Equals) per verificare se un elemento è presente.

1

Contains non è un'estensione LINQ e pertanto non è possibile utilizzare espressioni lambda con esso. È stato progettato per verificare se l'oggetto esiste nell'elenco.

Come altri hanno già detto, è un qualsiasi metodo di estensione compatibile equivalente lambda-espressione

Problemi correlati